-
Notifications
You must be signed in to change notification settings - Fork 84
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
acc97b9
commit 36e2507
Showing
8 changed files
with
404 additions
and
364 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
134 changes: 134 additions & 0 deletions
134
src/main/java/de/blau/android/layer/NetworkImageLoader.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
10
src/main/java/de/blau/android/layer/SelectImageInterface.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |
120 changes: 120 additions & 0 deletions
120
src/main/java/de/blau/android/layer/mapillary/AbstractSequenceFetcher.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
// } | ||
|
||
} |
Oops, something went wrong.