Skip to content

Commit

Permalink
WIP2
Browse files Browse the repository at this point in the history
  • Loading branch information
simonpoole committed Jan 13, 2025
1 parent acc97b9 commit 36e2507
Show file tree
Hide file tree
Showing 8 changed files with 404 additions and 364 deletions.
35 changes: 24 additions & 11 deletions src/main/java/de/blau/android/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@
import de.blau.android.layer.DownloadInterface;
import de.blau.android.layer.LayerType;
import de.blau.android.layer.MapViewLayer;
import de.blau.android.layer.NetworkImageLoader;
import de.blau.android.layer.SelectImageInterface;
import de.blau.android.layer.geojson.MapOverlay;
import de.blau.android.listener.UpdateViewListener;
import de.blau.android.osm.BoundingBox;
Expand Down Expand Up @@ -244,7 +246,7 @@ public class Main extends FullScreenAppCompatActivity
public static final String ACTION_EXIT = "de.blau.android.EXIT";
public static final String ACTION_UPDATE = "de.blau.android.UPDATE";
public static final String ACTION_DELETE_PHOTO = "de.blau.android.DELETE_PHOTO";
public static final String ACTION_MAPILLARY_SELECT = "de.blau.android.ACTION_MAPILLARY_SELECT";
public static final String ACTION_IMAGE_SELECT = "de.blau.android.ACTION_MAPILLARY_SELECT";
public static final String ACTION_MAP_UPDATE = "de.blau.android.MAP_UPDATE";
public static final String ACTION_PUSH_SELECTION = "de.blau.android.PUSH_SELECTION";
public static final String ACTION_POP_SELECTION = "de.blau.android.POP_SELECTION";
Expand Down Expand Up @@ -1005,16 +1007,11 @@ private void processIntents() {
photoLayer.invalidate();
}
break;
case ACTION_MAPILLARY_SELECT:
final de.blau.android.layer.mapillary.MapillaryOverlay mapillaryLayer = map != null
? (de.blau.android.layer.mapillary.MapillaryOverlay) map.getLayer(LayerType.MAPILLARY)
: null;
if (mapillaryLayer != null) {
double[] coords = intent.getDoubleArrayExtra(de.blau.android.layer.mapillary.MapillaryOverlay.COORDINATES_KEY);
if (coords != null) {
map.getViewBox().moveTo(map, (int) (coords[1] * 1E7), (int) (coords[0] * 1E7));
}
mapillaryLayer.select(intent.getIntExtra(de.blau.android.layer.mapillary.MapillaryOverlay.SET_POSITION_KEY, 0));
case ACTION_IMAGE_SELECT:
if (map != null) {
SelectImageInterface layer = (SelectImageInterface) map
.getLayer((LayerType) intent.getSerializableExtra(NetworkImageLoader.LAYER_TYPE_KEY));
selectImageOnLayer(intent, layer);
}
break;
case ACTION_MAP_UPDATE:
Expand Down Expand Up @@ -1075,6 +1072,22 @@ private void processIntents() {
}
}

/**
* Select an image on a layer
*
* @param intent the intent that we need to process
* @param layer the relevant layer
*/
private void selectImageOnLayer(Intent intent, final SelectImageInterface layer) {
if (layer != null) {
double[] coords = intent.getDoubleArrayExtra(NetworkImageLoader.COORDINATES_KEY);
if (coords != null) {
map.getViewBox().moveTo(map, (int) (coords[1] * 1E7), (int) (coords[0] * 1E7));
}
layer.selectImage(intent.getIntExtra(NetworkImageLoader.SET_POSITION_KEY, 0));
}
}

/**
* If we have been started by a shortcut, process mode and other setup here
*/
Expand Down
134 changes: 134 additions & 0 deletions src/main/java/de/blau/android/layer/NetworkImageLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package de.blau.android.layer;

import static de.blau.android.contract.Constants.LOG_TAG_LEN;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.davemorrissey.labs.subscaleview.ImageSource;
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.core.content.FileProvider;
import androidx.fragment.app.FragmentActivity;
import de.blau.android.App;
import de.blau.android.Main;
import de.blau.android.R;
import de.blau.android.contract.FileExtensions;
import de.blau.android.contract.MimeTypes;
import de.blau.android.contract.Schemes;
import de.blau.android.dialogs.ImageInfo;
import de.blau.android.util.ExecutorTask;
import de.blau.android.util.FileUtil;
import de.blau.android.util.ImageLoader;
import de.blau.android.util.ScreenMessage;

public abstract class NetworkImageLoader extends ImageLoader {
private static final long serialVersionUID = 1L;

private static final int TAG_LEN = Math.min(LOG_TAG_LEN, NetworkImageLoader.class.getSimpleName().length());
protected static final String DEBUG_TAG = NetworkImageLoader.class.getSimpleName().substring(0, TAG_LEN);

protected static final String JPG = "." + FileExtensions.JPG;

public static final String SET_POSITION_KEY = "set_position";
public static final String COORDINATES_KEY = "coordinates";
public static final String LAYER_TYPE_KEY = "layer_type";

protected final File cacheDir;
protected final long cacheSize;
protected final String imageUrl;
protected final Map<String, double[]> coordinates = new HashMap<>();
protected final List<String> ids;

/**
* Construct a new loader
*
* @param cacheDir the cacheDir that should be used as a destination for the images
* @param cacheSize max size of the cache
* @param imageUrl base url for retrieving the image
* @param ids list of images ids
*/
protected NetworkImageLoader(@NonNull File cacheDir, long cacheSize, @NonNull String imageUrl, List<String> ids) {
this.cacheDir = cacheDir;
this.cacheSize = cacheSize;
this.imageUrl = imageUrl;
this.ids = ids;
}

/**
* Prune the image cache
*/
protected void pruneCache() {
new ExecutorTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void arg) {
FileUtil.pruneCache(cacheDir, cacheSize);
return null;
}
}.execute();
}

/**
* Set the image
*
* @param view the ImageView to set it in
* @param imageFile the file
*/
protected void setImage(@NonNull SubsamplingScaleImageView view, @NonNull File imageFile) {
view.post(() -> { // needs to run on the ui thread
view.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_INSIDE);
view.setOrientation(SubsamplingScaleImageView.ORIENTATION_USE_EXIF);
view.setImage(ImageSource.uri(Uri.parse(Schemes.FILE + ":" + imageFile.getAbsolutePath())));
});
}

@Override
public void showOnMap(Context context, int index) {
if (!App.isPropertyEditorRunning()) {
Intent intent = new Intent(context, Main.class);
intent.setAction(Main.ACTION_IMAGE_SELECT);
intent.putExtra(SET_POSITION_KEY, index);
String key = ids.get(index);
if (key != null && coordinates.containsKey(key)) {
intent.putExtra(COORDINATES_KEY, coordinates.get(key));
}
intent.putExtra(LAYER_TYPE_KEY, getLayerType());
context.startActivity(intent);
}
}

/**
* Get the LayerType we are associated with
*
* @return a LayerType
*/
abstract protected LayerType getLayerType();

@Override
public void share(Context context, String key) {
File imageFile = new File(cacheDir, key + JPG);
if (imageFile.exists()) {
Uri f = FileProvider.getUriForFile(context, context.getString(R.string.content_provider), imageFile);
de.blau.android.layer.photos.Util.sharePhoto(context, key, f, MimeTypes.JPEG);
} else {
ScreenMessage.toastTopError(context, context.getString(R.string.toast_error_accessing_photo, key));
}
}

@Override
public boolean supportsInfo() {
return true;
}

@Override
public void info(@NonNull FragmentActivity activity, @NonNull String uri) {
Uri f = FileProvider.getUriForFile(activity, activity.getString(R.string.content_provider), new File(cacheDir, uri + JPG));
ImageInfo.showDialog(activity, f.toString());
}
}
10 changes: 10 additions & 0 deletions src/main/java/de/blau/android/layer/SelectImageInterface.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package de.blau.android.layer;

public interface SelectImageInterface {
/**
* Select a specific image in the selected sequence
*
* @param pos the position in the sequence
*/
public void selectImage(int pos);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package de.blau.android.layer.mapillary;

import static de.blau.android.contract.Constants.LOG_TAG_LEN;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import com.google.gson.JsonElement;
import com.google.gson.JsonParser;

import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import de.blau.android.App;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;

public abstract class AbstractSequenceFetcher implements Runnable {

private static final int TAG_LEN = Math.min(LOG_TAG_LEN, AbstractSequenceFetcher.class.getSimpleName().length());
private static final String DEBUG_TAG = AbstractSequenceFetcher.class.getSimpleName().substring(0, TAG_LEN);

protected final FragmentActivity activity;
final String urlTemplate;
protected final String sequenceId;
final String apiKey;

/**
* Construct a new instance
*
* @param activity the calling Activity
* @param sequenceId the sequence id
* @param id the image id
*/
public AbstractSequenceFetcher(@NonNull FragmentActivity activity, @NonNull String urlTemplate, @NonNull String sequenceId, @Nullable String apiKey) {
this.activity = activity;
this.urlTemplate = urlTemplate;
this.sequenceId = sequenceId;
this.apiKey = apiKey;
}

@Override
public void run() {
try {
URL url = new URL(String.format(urlTemplate, sequenceId, apiKey));
Log.d(DEBUG_TAG, "query sequence: " + url.toString());
Request request = new Request.Builder().url(url).build();
OkHttpClient client = App.getHttpClient().newBuilder().connectTimeout(20000, TimeUnit.MILLISECONDS).readTimeout(20000, TimeUnit.MILLISECONDS)
.build();
Call mapillaryCall = client.newCall(request);
Response mapillaryCallResponse = mapillaryCall.execute();
if (!mapillaryCallResponse.isSuccessful()) {
return;
}
ResponseBody responseBody = mapillaryCallResponse.body();
try (InputStream inputStream = responseBody.byteStream()) {
if (inputStream == null) {
throw new IOException("null InputStream");
}
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = inputStream.read()) != -1) {
sb.append((char) cp);
}
JsonElement root = JsonParser.parseString(sb.toString());
if (!root.isJsonObject()) {
throw new IOException("root is not a JsonObject");
}
ArrayList<String> ids = getIds(root);
saveIdsAndUpdate(ids);
}
} catch (IOException ex) {
Log.d(DEBUG_TAG, "query sequence failed with " + ex.getMessage());
}
}

/**
* @param ids
*/
abstract protected void saveIdsAndUpdate(ArrayList<String> ids);
// {
// if (state == null) {
// state = new State();
// }
// state.sequenceCache.put(sequenceId, ids);
// showImages(activity, id, ids);
// }

/**
* @param root
* @return
* @throws IOException
*/
abstract protected ArrayList<String> getIds(JsonElement root) throws IOException;
// {
// JsonElement data = ((JsonObject) root).get(DATA_KEY);
// if (!(data instanceof JsonArray)) {
// throw new IOException("data not a JsonArray");
// }
// JsonArray idArray = data.getAsJsonArray();
// ArrayList<String> ids = new ArrayList<>();
// for (JsonElement element : idArray) {
// if (element instanceof JsonObject) {
// JsonElement temp = ((JsonObject) element).get(ID_KEY);
// if (temp != null) {
// ids.add(temp.getAsString());
// }
// }
// }
// return ids;
// }

}
Loading

0 comments on commit 36e2507

Please sign in to comment.