Merge pull request #10668 from osmandapp/upload-photo-progress-bar
Upload Photo: bottom sheet with the progress bar
This commit is contained in:
commit
b3a712c47a
5 changed files with 416 additions and 137 deletions
48
OsmAnd/res/layout/bottom_sheet_with_progress_bar.xml
Normal file
48
OsmAnd/res/layout/bottom_sheet_with_progress_bar.xml
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="@dimen/bottom_sheet_selected_item_title_height"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingStart="@dimen/content_padding"
|
||||||
|
android:paddingLeft="@dimen/content_padding"
|
||||||
|
android:paddingTop="@dimen/measurement_tool_menu_title_padding_top"
|
||||||
|
android:paddingEnd="@dimen/content_padding"
|
||||||
|
android:paddingRight="@dimen/content_padding"
|
||||||
|
android:paddingBottom="@dimen/content_padding_small">
|
||||||
|
|
||||||
|
<net.osmand.plus.widgets.TextViewEx
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="?android:textColorPrimary"
|
||||||
|
android:textSize="@dimen/default_list_text_size"
|
||||||
|
osmand:typeface="@string/font_roboto_medium"
|
||||||
|
tools:text="Some title" />
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progress_bar"
|
||||||
|
style="?android:attr/progressBarStyleHorizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/route_info_buttons_padding_left_right"
|
||||||
|
android:layout_marginBottom="@dimen/route_info_buttons_padding_left_right"
|
||||||
|
android:minHeight="0dp"
|
||||||
|
android:visibility="visible" />
|
||||||
|
|
||||||
|
<net.osmand.plus.widgets.TextViewEx
|
||||||
|
android:id="@+id/description"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:lineSpacingMultiplier="@dimen/bottom_sheet_text_spacing_multiplier"
|
||||||
|
android:textColor="?android:textColorPrimary"
|
||||||
|
android:textSize="@dimen/default_list_text_size"
|
||||||
|
osmand:typeface="@string/font_roboto_regular"
|
||||||
|
tools:text="Some description" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -13,6 +13,10 @@
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<string name="toast_select_edits_for_upload">Select edits for upload</string>
|
<string name="toast_select_edits_for_upload">Select edits for upload</string>
|
||||||
|
<string name="uploaded_count">Uploaded %1$d of %2$d</string>
|
||||||
|
<string name="uploading_count">Uploading %1$d of %2$d</string>
|
||||||
|
<string name="upload_photo_completed">Upload completed</string>
|
||||||
|
<string name="upload_photo">Uploading</string>
|
||||||
<string name="copy_to_map_favorites">Copy to favorites</string>
|
<string name="copy_to_map_favorites">Copy to favorites</string>
|
||||||
<string name="copy_to_map_markers">Copy to map markers</string>
|
<string name="copy_to_map_markers">Copy to map markers</string>
|
||||||
<string name="delete_waypoints">Delete waypoints</string>
|
<string name="delete_waypoints">Delete waypoints</string>
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
package net.osmand.plus.dialogs;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.DialogInterface.OnDismissListener;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.UiUtilities;
|
||||||
|
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
|
||||||
|
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
|
||||||
|
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
|
||||||
|
import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerSpaceItem;
|
||||||
|
import net.osmand.plus.mapcontextmenu.UploadPhotosAsyncTask.UploadPhotosListener;
|
||||||
|
|
||||||
|
public class UploadPhotoProgressBottomSheet extends MenuBottomSheetDialogFragment implements UploadPhotosListener {
|
||||||
|
|
||||||
|
public static final String TAG = UploadPhotoProgressBottomSheet.class.getSimpleName();
|
||||||
|
|
||||||
|
private ProgressBar progressBar;
|
||||||
|
private TextView uploadedPhotosTitle;
|
||||||
|
private TextView uploadedPhotosCounter;
|
||||||
|
|
||||||
|
private OnDismissListener onDismissListener;
|
||||||
|
|
||||||
|
private int progress;
|
||||||
|
private int maxProgress;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createMenuItems(Bundle savedInstanceState) {
|
||||||
|
Context context = requireContext();
|
||||||
|
LayoutInflater inflater = UiUtilities.getInflater(context, nightMode);
|
||||||
|
View view = inflater.inflate(R.layout.bottom_sheet_with_progress_bar, null);
|
||||||
|
|
||||||
|
uploadedPhotosTitle = view.findViewById(R.id.title);
|
||||||
|
uploadedPhotosCounter = view.findViewById(R.id.description);
|
||||||
|
progressBar = view.findViewById(R.id.progress_bar);
|
||||||
|
progressBar.setMax(maxProgress);
|
||||||
|
String titleProgress = getString(progress == maxProgress? R.string.upload_photo_completed: R.string.upload_photo);
|
||||||
|
String descriptionProgress;
|
||||||
|
if (progress == maxProgress) {
|
||||||
|
descriptionProgress = getString(R.string.uploaded_count, progress, maxProgress);
|
||||||
|
} else {
|
||||||
|
descriptionProgress = getString(R.string.uploading_count, progress, maxProgress);
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseBottomSheetItem descriptionItem = new BottomSheetItemWithDescription.Builder()
|
||||||
|
.setDescription(descriptionProgress)
|
||||||
|
.setTitle(titleProgress)
|
||||||
|
.setCustomView(view)
|
||||||
|
.create();
|
||||||
|
items.add(descriptionItem);
|
||||||
|
|
||||||
|
updateProgress(progress);
|
||||||
|
|
||||||
|
int padding = getResources().getDimensionPixelSize(R.dimen.content_padding_small);
|
||||||
|
items.add(new DividerSpaceItem(context, padding));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxProgress(int maxProgress) {
|
||||||
|
this.maxProgress = maxProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnDismissListener(OnDismissListener onDismissListener) {
|
||||||
|
this.onDismissListener = onDismissListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateProgress(int progress) {
|
||||||
|
progressBar.setProgress(progress);
|
||||||
|
uploadedPhotosCounter.setText((getString(R.string.uploading_count, progress, maxProgress)));
|
||||||
|
uploadedPhotosTitle.setText(progress == maxProgress ? R.string.upload_photo_completed : R.string.upload_photo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uploadPhotosProgressUpdate(int progress) {
|
||||||
|
this.progress = progress;
|
||||||
|
updateProgress(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uploadPhotosFinished() {
|
||||||
|
updateProgress(maxProgress);
|
||||||
|
if (progress == maxProgress) {
|
||||||
|
uploadedPhotosCounter.setText((getString(R.string.uploaded_count, progress, maxProgress)));
|
||||||
|
setDismissButtonTextId(R.string.shared_string_close);
|
||||||
|
UiUtilities.setupDialogButton(nightMode, dismissButton, getDismissButtonType(), getDismissButtonTextId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDismiss(@NonNull DialogInterface dialog) {
|
||||||
|
super.onDismiss(dialog);
|
||||||
|
FragmentActivity activity = getActivity();
|
||||||
|
if (onDismissListener != null && activity != null && !activity.isChangingConfigurations()) {
|
||||||
|
onDismissListener.onDismiss(dialog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UploadPhotosListener showInstance(@NonNull FragmentManager fragmentManager, int maxProgress, OnDismissListener listener) {
|
||||||
|
UploadPhotoProgressBottomSheet fragment = new UploadPhotoProgressBottomSheet();
|
||||||
|
fragment.setRetainInstance(true);
|
||||||
|
fragment.setMaxProgress(maxProgress);
|
||||||
|
fragment.setOnDismissListener(listener);
|
||||||
|
fragmentManager.beginTransaction()
|
||||||
|
.add(fragment, UploadPhotoProgressBottomSheet.TAG)
|
||||||
|
.commitAllowingStateLoss();
|
||||||
|
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,22 +1,19 @@
|
||||||
package net.osmand.plus.mapcontextmenu;
|
package net.osmand.plus.mapcontextmenu;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.content.ClipData;
|
||||||
import android.content.ClipboardManager;
|
import android.content.ClipboardManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Matrix;
|
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.GradientDrawable;
|
import android.graphics.drawable.GradientDrawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Handler;
|
import android.os.Build;
|
||||||
import android.os.Looper;
|
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
@ -39,14 +36,12 @@ import androidx.core.content.ContextCompat;
|
||||||
import androidx.core.graphics.drawable.DrawableCompat;
|
import androidx.core.graphics.drawable.DrawableCompat;
|
||||||
|
|
||||||
import net.osmand.AndroidUtils;
|
import net.osmand.AndroidUtils;
|
||||||
import net.osmand.PlatformUtil;
|
|
||||||
import net.osmand.data.Amenity;
|
import net.osmand.data.Amenity;
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
import net.osmand.data.PointDescription;
|
import net.osmand.data.PointDescription;
|
||||||
import net.osmand.data.QuadRect;
|
import net.osmand.data.QuadRect;
|
||||||
import net.osmand.osm.PoiCategory;
|
import net.osmand.osm.PoiCategory;
|
||||||
import net.osmand.osm.PoiType;
|
import net.osmand.osm.PoiType;
|
||||||
import net.osmand.osm.io.NetworkUtils;
|
|
||||||
import net.osmand.plus.OsmAndFormatter;
|
import net.osmand.plus.OsmAndFormatter;
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
import net.osmand.plus.OsmandPlugin;
|
import net.osmand.plus.OsmandPlugin;
|
||||||
|
@ -54,6 +49,7 @@ import net.osmand.plus.R;
|
||||||
import net.osmand.plus.UiUtilities;
|
import net.osmand.plus.UiUtilities;
|
||||||
import net.osmand.plus.Version;
|
import net.osmand.plus.Version;
|
||||||
import net.osmand.plus.activities.ActivityResultListener;
|
import net.osmand.plus.activities.ActivityResultListener;
|
||||||
|
import net.osmand.plus.activities.ActivityResultListener.OnActivityResultListener;
|
||||||
import net.osmand.plus.activities.MapActivity;
|
import net.osmand.plus.activities.MapActivity;
|
||||||
import net.osmand.plus.helpers.FontCache;
|
import net.osmand.plus.helpers.FontCache;
|
||||||
import net.osmand.plus.mapcontextmenu.builders.cards.AbstractCard;
|
import net.osmand.plus.mapcontextmenu.builders.cards.AbstractCard;
|
||||||
|
@ -79,13 +75,6 @@ import net.osmand.plus.widgets.tools.ClickableSpanTouchListener;
|
||||||
import net.osmand.util.Algorithms;
|
import net.osmand.util.Algorithms;
|
||||||
import net.osmand.util.MapUtils;
|
import net.osmand.util.MapUtils;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.openplacereviews.opendb.util.exception.FailedVerificationException;
|
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
@ -99,8 +88,6 @@ import static net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCa
|
||||||
public class MenuBuilder {
|
public class MenuBuilder {
|
||||||
|
|
||||||
private static final int PICK_IMAGE = 1231;
|
private static final int PICK_IMAGE = 1231;
|
||||||
private static final int MAX_IMAGE_LENGTH = 2048;
|
|
||||||
private static final Log LOG = PlatformUtil.getLog(MenuBuilder.class);
|
|
||||||
public static final float SHADOW_HEIGHT_TOP_DP = 17f;
|
public static final float SHADOW_HEIGHT_TOP_DP = 17f;
|
||||||
public static final int TITLE_LIMIT = 60;
|
public static final int TITLE_LIMIT = 60;
|
||||||
protected static final String[] arrowChars = new String[] {"=>", " - "};
|
protected static final String[] arrowChars = new String[] {"=>", " - "};
|
||||||
|
@ -133,7 +120,6 @@ public class MenuBuilder {
|
||||||
private String preferredMapLang;
|
private String preferredMapLang;
|
||||||
private String preferredMapAppLang;
|
private String preferredMapAppLang;
|
||||||
private boolean transliterateNames;
|
private boolean transliterateNames;
|
||||||
private View view;
|
|
||||||
private View photoButton;
|
private View photoButton;
|
||||||
|
|
||||||
private final OpenDBAPI openDBAPI = new OpenDBAPI();
|
private final OpenDBAPI openDBAPI = new OpenDBAPI();
|
||||||
|
@ -270,7 +256,6 @@ public class MenuBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void build(View view) {
|
public void build(View view) {
|
||||||
this.view = view;
|
|
||||||
firstRow = true;
|
firstRow = true;
|
||||||
hidden = false;
|
hidden = false;
|
||||||
buildTopInternal(view);
|
buildTopInternal(view);
|
||||||
|
@ -425,7 +410,7 @@ public class MenuBuilder {
|
||||||
if (false) {
|
if (false) {
|
||||||
AddPhotosBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager());
|
AddPhotosBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager());
|
||||||
} else {
|
} else {
|
||||||
registerResultListener(view);
|
registerResultListener();
|
||||||
final String baseUrl = OPRConstants.getBaseUrl(app);
|
final String baseUrl = OPRConstants.getBaseUrl(app);
|
||||||
final String name = app.getSettings().OPR_USERNAME.get();
|
final String name = app.getSettings().OPR_USERNAME.get();
|
||||||
final String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
|
final String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
|
||||||
|
@ -443,6 +428,9 @@ public class MenuBuilder {
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.setType("image/*");
|
intent.setType("image/*");
|
||||||
intent.setAction(Intent.ACTION_GET_CONTENT);
|
intent.setAction(Intent.ACTION_GET_CONTENT);
|
||||||
|
if (Build.VERSION.SDK_INT > 18) {
|
||||||
|
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
|
||||||
|
}
|
||||||
mapActivity.startActivityForResult(Intent.createChooser(intent,
|
mapActivity.startActivityForResult(Intent.createChooser(intent,
|
||||||
mapActivity.getString(R.string.select_picture)), PICK_IMAGE);
|
mapActivity.getString(R.string.select_picture)), PICK_IMAGE);
|
||||||
}
|
}
|
||||||
|
@ -472,132 +460,33 @@ public class MenuBuilder {
|
||||||
false, null, false);
|
false, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerResultListener(final View view) {
|
private void registerResultListener() {
|
||||||
mapActivity.registerActivityResultListener(new ActivityResultListener(PICK_IMAGE, new ActivityResultListener.
|
mapActivity.registerActivityResultListener(new ActivityResultListener(PICK_IMAGE, new OnActivityResultListener() {
|
||||||
OnActivityResultListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onResult(int resultCode, Intent resultData) {
|
public void onResult(int resultCode, Intent resultData) {
|
||||||
if (resultData != null) {
|
if (resultData != null) {
|
||||||
handleSelectedImage(view, resultData.getData());
|
List<Uri> imagesUri = new ArrayList<>();
|
||||||
|
Uri data = resultData.getData();
|
||||||
|
if (data != null) {
|
||||||
|
imagesUri.add(data);
|
||||||
|
}
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||||
|
ClipData clipData = resultData.getClipData();
|
||||||
|
if (clipData != null) {
|
||||||
|
for (int i = 0; i < clipData.getItemCount(); i++) {
|
||||||
|
Uri uri = resultData.getClipData().getItemAt(i).getUri();
|
||||||
|
if (uri != null) {
|
||||||
|
imagesUri.add(uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
execute(new UploadPhotosAsyncTask(mapActivity, imagesUri, getLatLon(), placeId, getAdditionalCardParams(), imageCardListener));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSelectedImage(final View view, final Uri uri) {
|
|
||||||
Thread t = new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
InputStream inputStream = null;
|
|
||||||
try {
|
|
||||||
inputStream = app.getContentResolver().openInputStream(uri);
|
|
||||||
if (inputStream != null) {
|
|
||||||
uploadImageToPlace(inputStream);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.error(e);
|
|
||||||
String str = app.getString(R.string.cannot_upload_image);
|
|
||||||
showToastMessage(str);
|
|
||||||
} finally {
|
|
||||||
Algorithms.closeStream(inputStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
t.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void uploadImageToPlace(InputStream image) {
|
|
||||||
InputStream serverData = new ByteArrayInputStream(compressImageToJpeg(image));
|
|
||||||
final String baseUrl = OPRConstants.getBaseUrl(app);
|
|
||||||
// all these should be constant
|
|
||||||
String url = baseUrl + "api/ipfs/image";
|
|
||||||
String response = NetworkUtils.sendPostDataRequest(url, "file", "compressed.jpeg", serverData);
|
|
||||||
if (response != null) {
|
|
||||||
int res = 0;
|
|
||||||
try {
|
|
||||||
StringBuilder error = new StringBuilder();
|
|
||||||
String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
|
|
||||||
String username = app.getSettings().OPR_USERNAME.get();
|
|
||||||
res = openDBAPI.uploadImage(
|
|
||||||
placeId,
|
|
||||||
baseUrl,
|
|
||||||
privateKey,
|
|
||||||
username,
|
|
||||||
response, error);
|
|
||||||
if (res != 200) {
|
|
||||||
showToastMessage(error.toString());
|
|
||||||
} else {
|
|
||||||
//ok, continue
|
|
||||||
}
|
|
||||||
} catch (FailedVerificationException e) {
|
|
||||||
LOG.error(e);
|
|
||||||
checkTokenAndShowScreen();
|
|
||||||
}
|
|
||||||
if (res != 200) {
|
|
||||||
//image was uploaded but not added to blockchain
|
|
||||||
checkTokenAndShowScreen();
|
|
||||||
} else {
|
|
||||||
String str = app.getString(R.string.successfully_uploaded_pattern, 1, 1);
|
|
||||||
showToastMessage(str);
|
|
||||||
//refresh the image
|
|
||||||
execute(new GetImageCardsTask(mapActivity, getLatLon(), getAdditionalCardParams(), imageCardListener));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
checkTokenAndShowScreen();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showToastMessage(final String str) {
|
|
||||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Toast.makeText(mapActivity.getBaseContext(), str, Toast.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//This method runs on non main thread
|
|
||||||
private void checkTokenAndShowScreen() {
|
|
||||||
final String baseUrl = OPRConstants.getBaseUrl(app);
|
|
||||||
final String name = app.getSettings().OPR_USERNAME.get();
|
|
||||||
final String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
|
|
||||||
if (openDBAPI.checkPrivateKeyValid(baseUrl, name, privateKey)) {
|
|
||||||
String str = app.getString(R.string.cannot_upload_image);
|
|
||||||
showToastMessage(str);
|
|
||||||
} else {
|
|
||||||
app.runInUIThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
OprStartFragment.showInstance(mapActivity.getSupportFragmentManager());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] compressImageToJpeg(InputStream image) {
|
|
||||||
BufferedInputStream bufferedInputStream = new BufferedInputStream(image);
|
|
||||||
Bitmap bmp = BitmapFactory.decodeStream(bufferedInputStream);
|
|
||||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
|
||||||
int h = bmp.getHeight();
|
|
||||||
int w = bmp.getWidth();
|
|
||||||
boolean scale = false;
|
|
||||||
while (w > MAX_IMAGE_LENGTH || h > MAX_IMAGE_LENGTH) {
|
|
||||||
w = w / 2;
|
|
||||||
h = h / 2;
|
|
||||||
scale = true;
|
|
||||||
}
|
|
||||||
if (scale) {
|
|
||||||
Matrix matrix = new Matrix();
|
|
||||||
matrix.postScale(w, h);
|
|
||||||
Bitmap resizedBitmap = Bitmap.createBitmap(
|
|
||||||
bmp, 0, 0, w, h, matrix, false);
|
|
||||||
bmp.recycle();
|
|
||||||
bmp = resizedBitmap;
|
|
||||||
}
|
|
||||||
bmp.compress(Bitmap.CompressFormat.JPEG, 90, os);
|
|
||||||
return os.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startLoadingImages() {
|
private void startLoadingImages() {
|
||||||
if (onlinePhotoCardsRow == null) {
|
if (onlinePhotoCardsRow == null) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -0,0 +1,220 @@
|
||||||
|
package net.osmand.plus.mapcontextmenu;
|
||||||
|
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.DialogInterface.OnDismissListener;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Matrix;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import net.osmand.AndroidUtils;
|
||||||
|
import net.osmand.PlatformUtil;
|
||||||
|
import net.osmand.data.LatLon;
|
||||||
|
import net.osmand.osm.io.NetworkUtils;
|
||||||
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.activities.MapActivity;
|
||||||
|
import net.osmand.plus.dialogs.UploadPhotoProgressBottomSheet;
|
||||||
|
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask;
|
||||||
|
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask.GetImageCardsListener;
|
||||||
|
import net.osmand.plus.openplacereviews.OPRConstants;
|
||||||
|
import net.osmand.plus.openplacereviews.OprStartFragment;
|
||||||
|
import net.osmand.plus.osmedit.opr.OpenDBAPI;
|
||||||
|
import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.openplacereviews.opendb.util.exception.FailedVerificationException;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
|
||||||
|
|
||||||
|
private static final Log LOG = PlatformUtil.getLog(UploadPhotosAsyncTask.class);
|
||||||
|
|
||||||
|
private static final int MAX_IMAGE_LENGTH = 2048;
|
||||||
|
|
||||||
|
private final OsmandApplication app;
|
||||||
|
private final WeakReference<MapActivity> activityRef;
|
||||||
|
private UploadPhotosListener listener;
|
||||||
|
|
||||||
|
private final OpenDBAPI openDBAPI = new OpenDBAPI();
|
||||||
|
private final LatLon latLon;
|
||||||
|
private final List<Uri> data;
|
||||||
|
private final String[] placeId;
|
||||||
|
private final Map<String, String> params;
|
||||||
|
private final GetImageCardsListener imageCardListener;
|
||||||
|
|
||||||
|
public UploadPhotosAsyncTask(MapActivity activity, List<Uri> data, LatLon latLon, String[] placeId,
|
||||||
|
Map<String, String> params, GetImageCardsListener imageCardListener) {
|
||||||
|
app = (OsmandApplication) activity.getApplicationContext();
|
||||||
|
activityRef = new WeakReference<>(activity);
|
||||||
|
this.data = data;
|
||||||
|
this.latLon = latLon;
|
||||||
|
this.params = params;
|
||||||
|
this.placeId = placeId;
|
||||||
|
this.imageCardListener = imageCardListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPreExecute() {
|
||||||
|
FragmentActivity activity = activityRef.get();
|
||||||
|
if (AndroidUtils.isActivityNotDestroyed(activity)) {
|
||||||
|
FragmentManager manager = activity.getSupportFragmentManager();
|
||||||
|
listener = UploadPhotoProgressBottomSheet.showInstance(manager, data.size(), new OnDismissListener() {
|
||||||
|
@Override
|
||||||
|
public void onDismiss(DialogInterface dialog) {
|
||||||
|
cancel(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onProgressUpdate(Integer... values) {
|
||||||
|
if (listener != null) {
|
||||||
|
listener.uploadPhotosProgressUpdate(values[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Void doInBackground(Void... uris) {
|
||||||
|
for (int i = 0; i < data.size(); i++) {
|
||||||
|
if (isCancelled()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Uri uri = data.get(i);
|
||||||
|
handleSelectedImage(uri);
|
||||||
|
publishProgress(i + 1);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void aVoid) {
|
||||||
|
if (listener != null) {
|
||||||
|
listener.uploadPhotosFinished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleSelectedImage(final Uri uri) {
|
||||||
|
InputStream inputStream = null;
|
||||||
|
try {
|
||||||
|
inputStream = app.getContentResolver().openInputStream(uri);
|
||||||
|
if (inputStream != null) {
|
||||||
|
uploadImageToPlace(inputStream);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error(e);
|
||||||
|
app.showToastMessage(R.string.cannot_upload_image);
|
||||||
|
} finally {
|
||||||
|
Algorithms.closeStream(inputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uploadImageToPlace(InputStream image) {
|
||||||
|
InputStream serverData = new ByteArrayInputStream(compressImageToJpeg(image));
|
||||||
|
final String baseUrl = OPRConstants.getBaseUrl(app);
|
||||||
|
// all these should be constant
|
||||||
|
String url = baseUrl + "api/ipfs/image";
|
||||||
|
String response = NetworkUtils.sendPostDataRequest(url, "file", "compressed.jpeg", serverData);
|
||||||
|
if (response != null) {
|
||||||
|
int res = 0;
|
||||||
|
try {
|
||||||
|
StringBuilder error = new StringBuilder();
|
||||||
|
String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
|
||||||
|
String username = app.getSettings().OPR_USERNAME.get();
|
||||||
|
res = openDBAPI.uploadImage(
|
||||||
|
placeId,
|
||||||
|
baseUrl,
|
||||||
|
privateKey,
|
||||||
|
username,
|
||||||
|
response, error);
|
||||||
|
if (res != 200) {
|
||||||
|
app.showToastMessage(error.toString());
|
||||||
|
} else {
|
||||||
|
//ok, continue
|
||||||
|
}
|
||||||
|
} catch (FailedVerificationException e) {
|
||||||
|
LOG.error(e);
|
||||||
|
checkTokenAndShowScreen();
|
||||||
|
}
|
||||||
|
if (res != 200) {
|
||||||
|
//image was uploaded but not added to blockchain
|
||||||
|
checkTokenAndShowScreen();
|
||||||
|
} else {
|
||||||
|
String str = app.getString(R.string.successfully_uploaded_pattern, 1, 1);
|
||||||
|
app.showToastMessage(str);
|
||||||
|
//refresh the image
|
||||||
|
|
||||||
|
MapActivity activity = activityRef.get();
|
||||||
|
if (activity != null) {
|
||||||
|
MenuBuilder.execute(new GetImageCardsTask(activity, latLon, params, imageCardListener));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
checkTokenAndShowScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//This method runs on non main thread
|
||||||
|
private void checkTokenAndShowScreen() {
|
||||||
|
String baseUrl = OPRConstants.getBaseUrl(app);
|
||||||
|
String name = app.getSettings().OPR_USERNAME.get();
|
||||||
|
String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
|
||||||
|
if (openDBAPI.checkPrivateKeyValid(baseUrl, name, privateKey)) {
|
||||||
|
app.showToastMessage(R.string.cannot_upload_image);
|
||||||
|
} else {
|
||||||
|
app.runInUIThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
MapActivity activity = activityRef.get();
|
||||||
|
if (activity != null) {
|
||||||
|
OprStartFragment.showInstance(activity.getSupportFragmentManager());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] compressImageToJpeg(InputStream image) {
|
||||||
|
BufferedInputStream bufferedInputStream = new BufferedInputStream(image);
|
||||||
|
Bitmap bmp = BitmapFactory.decodeStream(bufferedInputStream);
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
int h = bmp.getHeight();
|
||||||
|
int w = bmp.getWidth();
|
||||||
|
boolean scale = false;
|
||||||
|
while (w > MAX_IMAGE_LENGTH || h > MAX_IMAGE_LENGTH) {
|
||||||
|
w = w / 2;
|
||||||
|
h = h / 2;
|
||||||
|
scale = true;
|
||||||
|
}
|
||||||
|
if (scale) {
|
||||||
|
Matrix matrix = new Matrix();
|
||||||
|
matrix.postScale(w, h);
|
||||||
|
Bitmap resizedBitmap = Bitmap.createBitmap(
|
||||||
|
bmp, 0, 0, w, h, matrix, false);
|
||||||
|
bmp.recycle();
|
||||||
|
bmp = resizedBitmap;
|
||||||
|
}
|
||||||
|
bmp.compress(Bitmap.CompressFormat.JPEG, 90, os);
|
||||||
|
return os.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface UploadPhotosListener {
|
||||||
|
|
||||||
|
void uploadPhotosProgressUpdate(int progress);
|
||||||
|
|
||||||
|
void uploadPhotosFinished();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue