From a310151b939ad76ca698faac8e7e6e14934e6379 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Fri, 8 Apr 2016 21:59:46 +0200 Subject: [PATCH 1/2] Replace WebView with new subclass ContextMenuWebView to allow long clicks on urls and images for sharing links, copying them to clipboard, saving images to external memory and opening them in external browsers. --- .../activity/MainActivity.java | 30 +++- .../ui/ContextMenuWebView.java | 153 ++++++++++++++++++ app/src/main/res/layout/content_main.xml | 2 +- app/src/main/res/values-de/strings.xml | 15 +- app/src/main/res/values/strings.xml | 14 +- 5 files changed, 208 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/MainActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/MainActivity.java index 8ca8598a..7c5be503 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/MainActivity.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/MainActivity.java @@ -69,6 +69,7 @@ import android.widget.ProgressBar; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.TextView; +import android.widget.Toast; import com.getbase.floatingactionbutton.FloatingActionsMenu; import com.github.dfa.diaspora_android.App; @@ -77,6 +78,7 @@ import com.github.dfa.diaspora_android.data.AppSettings; import com.github.dfa.diaspora_android.data.WebUserProfile; import com.github.dfa.diaspora_android.listener.SoftKeyboardStateWatcher; import com.github.dfa.diaspora_android.listener.WebUserProfileChangedListener; +import com.github.dfa.diaspora_android.ui.ContextMenuWebView; import com.github.dfa.diaspora_android.util.Helpers; import org.json.JSONException; @@ -96,6 +98,7 @@ public class MainActivity extends AppCompatActivity static final int INPUT_FILE_REQUEST_CODE = 1; private static final int REQUEST_CODE_ASK_PERMISSIONS = 123; + public static final int REQUEST_CODE_ASK_PERMISSIONS_SAVE_IMAGE = 124; private static final String URL_MESSAGE = "URL_MESSAGE"; private App app; @@ -120,7 +123,7 @@ public class MainActivity extends AppCompatActivity Toolbar toolbar; @Bind(R.id.webView) - WebView webView; + ContextMenuWebView webView; @Bind(R.id.fab_menubutton) FloatingActionsMenu fab; @@ -147,6 +150,9 @@ public class MainActivity extends AppCompatActivity appSettings = app.getSettings(); webUserProfile = new WebUserProfile(app, uiHandler, this); + this.registerForContextMenu(webView); + webView.setParentActivity(this); + // Setup toolbar setSupportActionBar(toolbar); toolbar.setOnClickListener(new View.OnClickListener() { @@ -599,7 +605,7 @@ public class MainActivity extends AppCompatActivity if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) { if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { new AlertDialog.Builder(MainActivity.this) - .setMessage(R.string.permissions) + .setMessage(R.string.permissions_screenshot) .setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { @@ -662,7 +668,7 @@ public class MainActivity extends AppCompatActivity if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) { if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { new AlertDialog.Builder(MainActivity.this) - .setMessage(R.string.permissions) + .setMessage(R.string.permissions_screenshot) .setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { @@ -1095,4 +1101,22 @@ public class MainActivity extends AppCompatActivity return true; } + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + switch (requestCode) { + case REQUEST_CODE_ASK_PERMISSIONS_SAVE_IMAGE: + if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + Toast.makeText(this, R.string.permission_granted_try_again, Toast.LENGTH_SHORT).show(); + } + else { + Toast.makeText(this, R.string.permission_denied, Toast.LENGTH_SHORT).show(); + } + return; + + default: + super.onRequestPermissionsResult(requestCode, permissions, + grantResults); + } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java new file mode 100644 index 00000000..2ecfa547 --- /dev/null +++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java @@ -0,0 +1,153 @@ +package com.github.dfa.diaspora_android.ui; + +import android.Manifest; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.DownloadManager; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Environment; +import android.util.AttributeSet; +import android.view.ContextMenu; +import android.view.MenuItem; +import android.webkit.WebView; +import android.widget.Toast; + +import com.github.dfa.diaspora_android.R; +import com.github.dfa.diaspora_android.activity.MainActivity; + +import java.io.File; + +/** + * Subclass of WebView which adds a context menu for long clicks on images or links to share, save + * or open with another browser + */ +public class ContextMenuWebView extends WebView { + + public static final int ID_SAVE_IMAGE = 10; + public static final int ID_EXTERNAL_BROWSER = 11; + public static final int ID_COPY_LINK = 12; + public static final int ID_SHARE_LINK = 13; + + private Context context; + private Activity parentActivity; + + public ContextMenuWebView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + this.context = context; + } + + public ContextMenuWebView(Context context, AttributeSet attrs) { + super(context, attrs); + this.context = context; + } + + @Override + protected void onCreateContextMenu(ContextMenu menu) { + super.onCreateContextMenu(menu); + + HitTestResult result = getHitTestResult(); + + MenuItem.OnMenuItemClickListener handler = new MenuItem.OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + HitTestResult result = getHitTestResult(); + String url = result.getExtra(); + switch(item.getItemId()) { + //Save image to external memory + case ID_SAVE_IMAGE: { + boolean writeToStoragePermitted = true; + if (android.os.Build.VERSION.SDK_INT >= 23) { + int hasWRITE_EXTERNAL_STORAGE = parentActivity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE); + if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) { + writeToStoragePermitted = false; + if (!parentActivity.shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + new AlertDialog.Builder(parentActivity) + .setMessage(R.string.permissions_images) + .setPositiveButton(context.getText(R.string.yes), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (android.os.Build.VERSION.SDK_INT >= 23) + parentActivity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + MainActivity.REQUEST_CODE_ASK_PERMISSIONS_SAVE_IMAGE); + } + }) + .setNegativeButton(context.getText(R.string.no), null) + .show(); + } + parentActivity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + MainActivity.REQUEST_CODE_ASK_PERMISSIONS_SAVE_IMAGE); + } + } + if(writeToStoragePermitted) { + if (url != null) { + Uri source = Uri.parse(url); + DownloadManager.Request request = new DownloadManager.Request(source); + File destinationFile = new File(Environment.getExternalStorageDirectory() + "/Pictures/Diaspora/" + + source.getLastPathSegment()); + request.setDestinationUri(Uri.fromFile(destinationFile)); + ((DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE)).enqueue(request); + Toast.makeText(context, context.getText(R.string.toast_saved_image_to_location) + " " + + destinationFile.getAbsolutePath(), Toast.LENGTH_LONG).show(); + } + } + } + break; + + case ID_EXTERNAL_BROWSER: + if(url != null) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + context.startActivity(intent); + } + break; + + //Copy url to clipboard + case ID_COPY_LINK: + if(url != null) { + ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + clipboard.setPrimaryClip(ClipData.newPlainText("text", url)); + Toast.makeText(context, R.string.toast_link_address_copied, Toast.LENGTH_SHORT).show(); + } + break; + + //Try to share link to other apps + case ID_SHARE_LINK: + if(url != null) { + Intent sendIntent = new Intent(); + sendIntent.setAction(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_TEXT, url); + sendIntent.setType("text/plain"); + context.startActivity(Intent.createChooser(sendIntent, getResources() + .getText(R.string.context_menu_share_link))); + } + break; + } + return true; + } + }; + + //Build context menu + if (result.getType() == HitTestResult.IMAGE_TYPE || + result.getType() == HitTestResult.SRC_IMAGE_ANCHOR_TYPE) { + // Menu options for an image. + menu.setHeaderTitle(result.getExtra()); + menu.add(0, ID_SAVE_IMAGE, 0, context.getString(R.string.context_menu_save_image)).setOnMenuItemClickListener(handler); + menu.add(0, ID_EXTERNAL_BROWSER, 0, context.getString(R.string.context_menu_open_external_browser)).setOnMenuItemClickListener(handler); + } + else if (result.getType() == HitTestResult.ANCHOR_TYPE || + result.getType() == HitTestResult.SRC_ANCHOR_TYPE) { + // Menu options for a hyperlink. + menu.setHeaderTitle(result.getExtra()); + menu.add(0, ID_COPY_LINK, 0, context.getString(R.string.context_menu_copy_link)).setOnMenuItemClickListener(handler); + menu.add(0, ID_SHARE_LINK, 0, context.getString(R.string.context_menu_share_link)).setOnMenuItemClickListener(handler); + } + } + + public void setParentActivity(Activity activity) { + this.parentActivity = activity; + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml index 074bfa1c..762e6197 100644 --- a/app/src/main/res/layout/content_main.xml +++ b/app/src/main/res/layout/content_main.xml @@ -13,7 +13,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - NEIN Das wird alle Cookies und Session-Daten löschen. Willst du wirklich den Pod wechseln? - Du musst der App Zugriff auf den Gerätespeicher gewähren, damit das Bildschirmfoto + Du musst der App Zugriff auf den Gerätespeicher gewähren, damit das Bildschirmfoto gespeichert werden kann. Danach solltest du die Anwendung komplett schließen oder das Telefon neu starten. Wenn du den Zugriff verweigerst und die Funktion später doch nutzen willst, kannst du die Berechtigung nachträglich erteilen. Öffne dafür: Systemeinstellungen - Apps - Wetter. Im Bereich Berechtigungen kannst dann die entsprechende Einstellung vornehmen. + Du musst der App Zugriff auf den Gerätespeicher gewähren, damit das Bild + gespeichert werden kann. Danach solltest du die Anwendung komplett schließen oder das Telefon neu starten. + Wenn du den Zugriff verweigerst und die Funktion später doch nutzen willst, kannst du die Berechtigung + nachträglich erteilen. Öffne dafür: Systemeinstellungen - Apps - Wetter. Im Bereich Berechtigungen kannst + dann die entsprechende Einstellung vornehmen. + Berechtigung verweigert. + Berechtigung erteilt. Bitte versuche es erneut. // Drawer and App @@ -154,5 +161,11 @@ along with this program. If not, see http://www.gnu.org/licenses.<br> <br *[geteilt durch #DiasporaForAndroid]* Bilder nicht laden Bilder laden + Bild speichern + Linkadresse kopieren + Linkadresse teilen + In externem Browser öffnen… + Speichere Bild als + Linkadresse kopiert … diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 653cab51..50c880cb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -8,10 +8,16 @@ Reload Unread notification. Want to read it? Unread conversation. Open it? - You must grant \"Access Storage Permission\" to save screenshots. After that you should + You must grant \"Access Storage Permission\" to save screenshots. After that you should completely close the app or restart the phone. If you don\'t permit the storage access but want to use the screenshot function at a later time, you can grant the permission later. Please open then: systemsettings - apps - weather. In the permissions section you can grant the \"write storage permission\". + You must grant \"Access Storage Permission\" to save images. After that you should + completely close the app or restart the phone. If you don\'t permit the storage access but want to save images + at a later time, you can grant the permission later. Please open then: systemsettings - apps - + weather. In the permissions section you can grant the \"write storage permission\". + Permission denied. + Permission granted. Please try again. //Pod Activity @@ -198,4 +204,10 @@ Exit app Diaspora *[shared by #DiasporaForAndroid]* + Link address copied … + Share link address + Save image + Open in external browser … + Copy link address to clipboard + Saving image to From f137cd12bccaf734b74de44614a8968da5ec36de Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Fri, 8 Apr 2016 22:11:01 +0200 Subject: [PATCH 2/2] Fixed typo in string resource name --- .../com/github/dfa/diaspora_android/ui/ContextMenuWebView.java | 2 +- app/src/main/res/values-de/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java index 2ecfa547..d9083064 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java @@ -67,7 +67,7 @@ public class ContextMenuWebView extends WebView { writeToStoragePermitted = false; if (!parentActivity.shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { new AlertDialog.Builder(parentActivity) - .setMessage(R.string.permissions_images) + .setMessage(R.string.permissions_image) .setPositiveButton(context.getText(R.string.yes), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index f95b00f3..3b4ef40a 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -22,7 +22,7 @@ Wenn du den Zugriff verweigerst und die Funktion später doch nutzen willst, kannst du die Berechtigung nachträglich erteilen. Öffne dafür: Systemeinstellungen - Apps - Wetter. Im Bereich Berechtigungen kannst dann die entsprechende Einstellung vornehmen. - Du musst der App Zugriff auf den Gerätespeicher gewähren, damit das Bild + Du musst der App Zugriff auf den Gerätespeicher gewähren, damit das Bild gespeichert werden kann. Danach solltest du die Anwendung komplett schließen oder das Telefon neu starten. Wenn du den Zugriff verweigerst und die Funktion später doch nutzen willst, kannst du die Berechtigung nachträglich erteilen. Öffne dafür: Systemeinstellungen - Apps - Wetter. Im Bereich Berechtigungen kannst