Статья предназначена для тех, у кого трудности с подключением infoWindow в osmdroid и работой с AsyncTask и просто для тех, кто раньше не делал ничего подобного. Здесь я писал о том, как я создавал окошко для получения данных об автомобиле в сервисе мониторинга транспорта.
Суть в том, что при нажатии на маркер, некоторые данные берутся из объекта, другие данные подгружаются из API, записываются в БД приложения, после чего отображаются в объекте InfoWindow.
Начинаем с создания xml файла с описанием infoWindow, добавляем поля с заголовками критериев транспорта.
MarkerInfoWindow позволяет записывать в Title, Description, Subdescription, я использовал только Descripton для всех нужных записей. Будем впоследствии передавать туда данные в виде строки с переносами.
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@drawable/balloon_overlay_white" >
<ImageView android:id="@+id/bubble_image"
android:layout_width="65dp"
android:layout_height="65dp"
android:visibility="gone" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="5dp"
android:orientation="vertical" >
<TextView android:id="@+id/bubble_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:maxEms="17"
android:layout_gravity="left"
android:layout_weight="1"
android:text="Title"
android:textSize="18dp"
android:textIsSelectable="false" />
<Button android:id="@+id/bubble_moreinfo"
android:background="@drawable/btn_moreinfo"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_weight="0" />
<TextView android:id="@+id/bubble_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14dp"
android:maxEms="17"
android:text="Description"
android:layout_toRightOf="@+id/model"
android:layout_below="@+id/bubble_title"
android:lineSpacingExtra="3dp"
android:layout_marginLeft="3dp" />
<TextView android:id="@+id/model"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff6c6c6c"
android:textSize="14dp"
android:maxEms="17"
android:text="@string/model"
android:layout_below="@+id/bubble_title"
android:layout_alignRight="@+id/organization" />
<TextView android:id="@+id/group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff6c6c6c"
android:textSize="14dp"
android:maxEms="17"
android:text="@string/group"
android:layout_below="@+id/model"
android:layout_alignRight="@+id/organization" />
<TextView android:id="@+id/organization"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff6c6c6c"
android:textSize="14dp"
android:maxEms="17"
android:text="@string/organization"
android:layout_below="@+id/group" />
<TextView android:id="@+id/speed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff6c6c6c"
android:textSize="14dp"
android:maxEms="17"
android:text="@string/speed"
android:layout_below="@+id/organization"
android:layout_alignRight="@+id/organization" />
<TextView android:id="@+id/update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff6c6c6c"
android:textSize="14dp"
android:maxEms="17"
android:text="@string/update"
android:layout_below="@+id/speed"
android:layout_alignRight="@+id/organization" />
<TextView android:id="@+id/bubble_subdescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:textSize="10dp"
android:maxEms="17"
android:text="Address"
android:layout_below="@+id/update" />
</RelativeLayout>
</LinearLayout>
public class CarInfoWindow extends MarkerInfoWindow {
Car mCar;
Marker mMarker;
CarInfoTask carInfoTask;
Boolean stopped = false;
Drawable icon;
String active;
public CarInfoWindow(int layoutResId, MapView mapView) {
super(layoutResId, mapView);
}
//при открытии запускаем asyncTask
@Override
public void onOpen(final Object item) {
if (!stopped) {
carInfoTask = new CarInfoTask();
carInfoTask.execute(item);
}
super.onOpen(item);
}
//при закрытии можем поменять иконку маркера
@Override
public void onClose() {
stopped = false;
super.onClose();
if (!(mCar.getLastUpdate() == null)) {
if (((System.currentTimeMillis() - Long.parseLong(mCar.getLastUpdate())) / 3600000) > 1) {
active = "0"; //car is not active
}
else {
active = "1";
}
}
String fileName = Environment.getExternalStorageDirectory()+"/automap/cars/icons/"+mCar.getIconIndex()+"/"+active+"/icon.png";
icon = Utils.loadIcon(fileName, Float.parseFloat(mCar.getDirection()), mCar.getIconType());
mMarker.setIcon(icon);
}
class CarInfoTask extends AsyncTask<Object, String, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
//операции по обработке данных производятся в этом методе
protected Void doInBackground(Object... params) {
try {
//задаем нужный маркер, к которому привязан объект Car с нужными данными
mMarker = (Marker)params[0];
mCar = (Car) mMarker.getRelatedObject();
//Данные, которые нужно передать в infoWindow
String markName;
String carModelName;
String groupName;
String carLastUpdate;
Context context = getView().getContext();
//берем token, и данные из объекта
Token token = Prefs.getToken(getView().getContext());
String markId = mCar.getMarkId();
String modelId = mCar.getModelId();
String orgId = mCar.getOrganizationId();
String groupId = mCar.getGroupId();
carLastUpdate = mCar.getLastUpdate();
//что-нибудь делаем
String formattedDate = "";
if (!(carLastUpdate == null)) {
long unixSeconds = Long.parseLong(carLastUpdate);
Date date = new Date(unixSeconds);
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss ");
formattedDate = sdf.format(date);
}
String organizationName = DbHelper.getInstance(context).getOrganizationStatById(orgId).getName();
List<Mark> marksList = null;
List<CarModel> carModelsList = null;
List<Group> groupsList = null;
//делаем запрос в API, берем mark и model по id
try {
//используем retrofit
carModelsList = Api.getService(context).getModels(token.getValue(), markId);
int size = carModelsList.size();
for (int i=0; i<size; i++) {
//используем cupboard для сохранения данных в БД
DbHelper.getInstance(context).insertCarModels(carModelsList.get(i));
}
groupsList = Api.getService(context).getGroups(token.getValue(), orgId);
size = groupsList.size();
for (int i=0; i<size; i++) {
DbHelper.getInstance(context).insertGroups(groupsList.get(i));
}
} catch (Exception e) {
e.printStackTrace();
}
markName = DbHelper.getInstance(context).getMarkById(markId).getName();
carModelName = DbHelper.getInstance(context).getCarModelById(modelId).getName();
groupName = DbHelper.getInstance(context).getGroupById(groupId).getName();
//записываем нужные данные сюда для передачи в UI.
publishProgress(organizationName, markName, carModelName, groupName, formattedDate);
//values[0] = organizationName, values[1] = markName и т.д.
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
//отображаем данные в textView, которые были переданые методом publishProgress()
mMarker.hideInfoWindow();
mMarker.setTitle(mCar.getCarNo() + " (" + values[1] + ")");
mMarker.setSnippet(
values[2] + "n" +
values[3] + "n" +
values[0] + "n" +
mCar.getSpeed() + "n" +
values[4]
);
mMarker.setSubDescription("");
//можем поменять иконку маркера
String fileName = Environment.getExternalStorageDirectory()+"/automap/cars/icons/"+mCar.getIconIndex()+"/2/icon.png";
icon = Utils.loadIcon(fileName, Float.parseFloat(mCar.getDirection()), mCar.getIconType());
mMarker.setIcon(icon);
}
//метод, в котором мы останавливаем asyncTask
@Override
protected void onPostExecute(Void result) {
stopped = true;
mMarker.showInfoWindow();
super.onPostExecute(result);
}
}
}
Теперь при создании маркера остается всего лишь к маркеру привязать нужное окно
marker.setInfoWindow(infoWindow);
В результате проделанных манипуляций получаем нечто вроде:
P.S. Несмотря на то, что маркер — иконка грузовика, а в описании это Alfa Romeo, всё работает верно.
Автор: borisov_a_s