From d7adce9782cc6d8e5f56e1fe660d4030e6c112e0 Mon Sep 17 00:00:00 2001 From: Martin Williams Date: Mon, 9 Sep 2024 11:49:41 +0100 Subject: [PATCH 1/5] Protect against external activity failure --- .../com/samsung/microbit/ui/FetchPopups.java | 9 ++ .../java/com/samsung/microbit/ui/UIUtils.java | 94 +++++++++++++++++++ .../microbit/ui/activity/FetchActivity.java | 52 ++++++---- .../microbit/ui/activity/HomeActivity.java | 21 ++--- .../microbit/ui/activity/MakeCodeWebView.java | 37 +++++--- .../microbit/ui/activity/PairingActivity.java | 35 ++++++- .../microbit/ui/activity/ProjectActivity.java | 19 +++- app/src/main/res/values/strings.xml | 6 +- 8 files changed, 219 insertions(+), 54 deletions(-) diff --git a/app/src/main/java/com/samsung/microbit/ui/FetchPopups.java b/app/src/main/java/com/samsung/microbit/ui/FetchPopups.java index 03b06496..6849634f 100644 --- a/app/src/main/java/com/samsung/microbit/ui/FetchPopups.java +++ b/app/src/main/java/com/samsung/microbit/ui/FetchPopups.java @@ -59,6 +59,15 @@ public void bluetoothOff() { popupClickActivityCancelled, popupClickActivityCancelled); } + public void bluetoothEnableRestricted() { + PopUp.show( mClient.fetchPopupsContext().getString(R.string.this_device_may_have_restrictions_in_place), //message + mClient.fetchPopupsContext().getString(R.string.unable_to_start_activity_to_enable_bluetooth), + R.drawable.error_face, R.drawable.red_btn, + PopUp.GIFF_ANIMATION_ERROR, + PopUp.TYPE_ALERT, + popupClickActivityCancelled, popupClickActivityCancelled); + } + public void bluetoothConnectPermissionError() { PopUp.show(mClient.fetchPopupsContext().getString(R.string.ble_permission_connect_error), mClient.fetchPopupsContext().getString(R.string.permissions_needed_title), diff --git a/app/src/main/java/com/samsung/microbit/ui/UIUtils.java b/app/src/main/java/com/samsung/microbit/ui/UIUtils.java index a85a129b..cfa51446 100644 --- a/app/src/main/java/com/samsung/microbit/ui/UIUtils.java +++ b/app/src/main/java/com/samsung/microbit/ui/UIUtils.java @@ -1,10 +1,16 @@ package com.samsung.microbit.ui; import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Point; import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Bundle; import android.util.Log; import android.util.TypedValue; import android.view.View; @@ -271,4 +277,92 @@ public void gifAnimate( @IdRes int id) { view.animate(); } } + + public static void safelyStartActivityPopup( String message, String title) { + PopUp.show( message, title, + R.drawable.error_face, + R.drawable.red_btn, + PopUp.GIFF_ANIMATION_ERROR, + PopUp.TYPE_ALERT, + null, + null); + + } + public static void safelyStartActivityPopup( Context context, String title) { + safelyStartActivityPopup( context.getString(R.string.this_device_may_have_restrictions_in_place), title); + } + + public static void safelyStartActivityPopupGeneric( Context context) { + safelyStartActivityPopup( context, context.getString(R.string.unable_to_start_activity)); + } + + public static void safelyStartActivityPopupOpenLink( Context context) { + safelyStartActivityPopup( context, context.getString(R.string.unable_to_open_link)); + } + + // Wrap startActivity and startActivityForResult + // Call resolveActivity and catch exception from startActivity + // Return non-zero error on fail + // When startActivityForResult fails, the caller likely + // needs to add code similar to the cancel case in onActivityResult + public static int safelyStartActivity( Context context, boolean report, Intent intent, + boolean forResult, int requestCode, Bundle options) { + int error = 0; + ComponentName componentName = intent.resolveActivity( context.getPackageManager()); + if ( componentName == null) { + Log.i(TAG,"startActivity - no component"); + error = 1; + } else { + try { + if ( forResult) { + if ( !(context instanceof Activity)) { + error = 3; + } else { + ((Activity) context).startActivityForResult(intent, requestCode, options); + } + } else { + context.startActivity(intent); + } + } catch (Exception e) { + Log.i(TAG, "startActivity - exception"); + e.printStackTrace(); + error = 2; + } + } + if ( report && error != 0) + { + safelyStartActivityPopupGeneric( context); + } + return error; + } + + public static int safelyStartActivity(Context context, boolean report, Intent intent, Bundle options) { + return UIUtils.safelyStartActivity( context, report, intent, false, 0, options); + } + + public static int safelyStartActivity(Context context, boolean report, Intent intent) { + return UIUtils.safelyStartActivity( context, report, intent, null); + } + + public static int safelyStartActivityForResult(Activity activity, boolean report, Intent intent, int requestCode, Bundle options) { + return UIUtils.safelyStartActivity( activity, report, intent, true, requestCode, options); + } + + public static int safelyStartActivityForResult(Activity activity, boolean report, Intent intent, int requestCode) { + return UIUtils.safelyStartActivityForResult( activity, report, intent, requestCode, null); + } + + public static int safelyStartActivityViewURI( Context context, boolean report, Uri uri) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData( uri); + int error = UIUtils.safelyStartActivity( context, false, intent); + if ( report && error != 0) { + safelyStartActivityPopupOpenLink( context); + } + return error; + } + + public static int safelyStartActivityViewURL( Context context, boolean report, String url) { + return UIUtils.safelyStartActivityViewURI( context, report, Uri.parse( url)); + } } diff --git a/app/src/main/java/com/samsung/microbit/ui/activity/FetchActivity.java b/app/src/main/java/com/samsung/microbit/ui/activity/FetchActivity.java index 26e28b43..d8454b89 100644 --- a/app/src/main/java/com/samsung/microbit/ui/activity/FetchActivity.java +++ b/app/src/main/java/com/samsung/microbit/ui/activity/FetchActivity.java @@ -360,6 +360,14 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { } dataToSave = null; break; + case REQUEST_CODE_CHOOSE_FILE: + if ( resultCode != RESULT_OK) { + mWebFileChooserCallback.onReceiveValue( null); + return; + } + Uri[] uris = WebChromeClient.FileChooserParams.parseResult ( resultCode, data); + mWebFileChooserCallback.onReceiveValue( uris); + break; } } @@ -468,9 +476,7 @@ public void onClick(final View v) { break; case R.id.fetchSelectDuringMore: - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(getString(R.string.fetchDuringFindOutMoreUrl))); - startActivity(intent); + UIUtils.safelyStartActivityViewURL( this, true, getString(R.string.fetchDuringFindOutMoreUrl)); break; } } @@ -675,7 +681,10 @@ private MBAppState.PairState pairState() { @SuppressLint("MissingPermission") private void enableBluetooth() { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); - startActivityForResult(enableBtIntent, RequestCodes.REQUEST_ENABLE_BT); + int error = UIUtils.safelyStartActivityForResult( this, false, enableBtIntent, RequestCodes.REQUEST_ENABLE_BT); + if ( error != 0) { + mPopups.bluetoothEnableRestricted(); + } } private boolean havePermission(String permission) { @@ -869,9 +878,7 @@ private void displayUpdateDeviceName() { private void openURL( String url) { logi( "openURL: " + url); - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse( url)); - startActivity(intent); + UIUtils.safelyStartActivityViewURL( this, true, url); } /** @@ -938,16 +945,7 @@ public void onPageFinished(WebView view, String url) { mWebView.setWebChromeClient(new WebChromeClient() { @Override public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { - mWebFileChooserCallback = filePathCallback; - try { - Intent intent = fileChooserParams.createIntent(); - startActivityForResult(intent, REQUEST_CODE_CHOOSE_FILE); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - return true; - + return onShowFileChooser( webView, filePathCallback, fileChooserParams); } }); //setWebChromeClient @@ -981,6 +979,21 @@ public void onDownloadBase64( String base64, String mimetype) { } } + private boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { + mWebFileChooserCallback = filePathCallback; + try { + Intent intent = fileChooserParams.createIntent(); + int error = UIUtils.safelyStartActivityForResult( this, true, intent, REQUEST_CODE_CHOOSE_FILE); + if ( error != 0) { + mWebFileChooserCallback.onReceiveValue( null); + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } + private void onDownloadBlob( String blob) { String js = "javascript:(" + "function f() {" @@ -1032,7 +1045,10 @@ private void saveData( String name, String mimetype, byte[] data) { intent.setType( mimetype); intent.putExtra(Intent.EXTRA_TITLE, name); dataToSave = data; - startActivityForResult( intent, REQUEST_CODE_SAVEDATA); + int error = UIUtils.safelyStartActivityForResult( this, true, intent, REQUEST_CODE_SAVEDATA); + if ( error != 0) { + dataToSave = null; + } } private String displayHtmlGetPath() { diff --git a/app/src/main/java/com/samsung/microbit/ui/activity/HomeActivity.java b/app/src/main/java/com/samsung/microbit/ui/activity/HomeActivity.java index 43e221c2..60881ee6 100644 --- a/app/src/main/java/com/samsung/microbit/ui/activity/HomeActivity.java +++ b/app/src/main/java/com/samsung/microbit/ui/activity/HomeActivity.java @@ -42,6 +42,7 @@ import com.samsung.microbit.data.model.ConnectedDevice; import com.samsung.microbit.service.IPCService; import com.samsung.microbit.ui.PopUp; +import com.samsung.microbit.ui.UIUtils; import com.samsung.microbit.utils.FileUtils; import com.samsung.microbit.utils.ProjectsHelper; import com.samsung.microbit.utils.Utils; @@ -393,9 +394,7 @@ public void onClick(final View v) { startActivity(i); break; case R.id.discover_btn: - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(getString(R.string.discover_url))); - startActivity(intent); + UIUtils.safelyStartActivityViewURL( this, true, getString(R.string.discover_url)); break; // TODO: HACK - Navigation View items from drawer here instead of [onNavigationItemSelected] @@ -406,9 +405,7 @@ public void onClick(final View v) { } break; case R.id.btn_about: { - Intent aboutIntent = new Intent(Intent.ACTION_VIEW); - aboutIntent.setData(Uri.parse(getString(R.string.about_url))); - startActivity(aboutIntent); + UIUtils.safelyStartActivityViewURL( this, true, getString(R.string.about_url)); // Close drawer drawer.closeDrawer(GravityCompat.START); } @@ -422,19 +419,13 @@ public void onClick(final View v) { } break; case R.id.btn_privacy_cookies: { - - Intent privacyIntent = new Intent(Intent.ACTION_VIEW); - privacyIntent.setData(Uri.parse(getString(R.string.privacy_policy_url))); - startActivity(privacyIntent); + UIUtils.safelyStartActivityViewURL( this, true, getString(R.string.privacy_policy_url)); // Close drawer drawer.closeDrawer(GravityCompat.START); } break; case R.id.btn_terms_conditions: { - - Intent termsIntent = new Intent(Intent.ACTION_VIEW); - termsIntent.setData(Uri.parse(getString(R.string.terms_of_use_url))); - startActivity(termsIntent); + UIUtils.safelyStartActivityViewURL( this, true, getString(R.string.terms_of_use_url)); // Close drawer drawer.closeDrawer(GravityCompat.START); } @@ -449,7 +440,7 @@ public void onClick(final View v) { String body = prepareEmailBody(); feedbackIntent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(body)); Intent mailer = Intent.createChooser(feedbackIntent, null); - startActivity(mailer); + UIUtils.safelyStartActivity( this, true, mailer); // Close drawer if(drawer != null) { drawer.closeDrawer(GravityCompat.START); diff --git a/app/src/main/java/com/samsung/microbit/ui/activity/MakeCodeWebView.java b/app/src/main/java/com/samsung/microbit/ui/activity/MakeCodeWebView.java index 51023d62..071f0029 100644 --- a/app/src/main/java/com/samsung/microbit/ui/activity/MakeCodeWebView.java +++ b/app/src/main/java/com/samsung/microbit/ui/activity/MakeCodeWebView.java @@ -22,6 +22,7 @@ import com.samsung.microbit.BuildConfig; import com.samsung.microbit.MBApp; import com.samsung.microbit.R; +import com.samsung.microbit.ui.UIUtils; import com.samsung.microbit.utils.FileUtils; import com.samsung.microbit.utils.ProjectsHelper; @@ -135,15 +136,7 @@ public void onPageFinished (WebView view, String url) { webView.setWebChromeClient(new WebChromeClient() { @Override public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { - onShowFileChooser_filePathCallback = filePathCallback; - try { - Intent intent = fileChooserParams.createIntent(); - startActivityForResult(intent, REQUEST_CODE_CHOOSE_FILE); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - return true; + return onShowFileChooser( webView, filePathCallback, fileChooserParams); } }); //setWebChromeClient @@ -268,6 +261,23 @@ else if ( !hexName.isEmpty()) { } // onCreate + private boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { + onShowFileChooser_filePathCallback = filePathCallback; + try { + Intent intent = fileChooserParams.createIntent(); + int error = UIUtils.safelyStartActivityForResult( this, true, intent, REQUEST_CODE_CHOOSE_FILE); + if ( error != 0) { + onShowFileChooser_filePathCallback.onReceiveValue( null); + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + + } + + private boolean overrideUri( final Uri uri) { String url = uri.toString().toLowerCase(); Log.v(TAG, "overrideUri: " + url); @@ -333,9 +343,7 @@ else if ( host.equals( "github.com")) { void openUri( Uri uri) { Log.v(TAG, "openUri: " + uri); - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData( uri); - startActivity(intent); + UIUtils.safelyStartActivityViewURI( this, true, uri); } private void saveData( String name, String mimetype, byte[] data) { @@ -344,7 +352,10 @@ private void saveData( String name, String mimetype, byte[] data) { intent.setType( mimetype); intent.putExtra(Intent.EXTRA_TITLE, name); dataToSave = data; - startActivityForResult( intent, REQUEST_CODE_SAVEDATA); + int error = UIUtils.safelyStartActivityForResult( this, true, intent, REQUEST_CODE_SAVEDATA); + if ( error != 0) { + dataToSave = null; + } } @Override diff --git a/app/src/main/java/com/samsung/microbit/ui/activity/PairingActivity.java b/app/src/main/java/com/samsung/microbit/ui/activity/PairingActivity.java index 6754ff3a..20ea2fe5 100644 --- a/app/src/main/java/com/samsung/microbit/ui/activity/PairingActivity.java +++ b/app/src/main/java/com/samsung/microbit/ui/activity/PairingActivity.java @@ -50,6 +50,7 @@ import com.samsung.microbit.service.BLEService; import com.samsung.microbit.ui.BluetoothChecker; import com.samsung.microbit.ui.PopUp; +import com.samsung.microbit.ui.UIUtils; import com.samsung.microbit.ui.adapter.LEDAdapter; import com.samsung.microbit.utils.BLEConnectionHandler; import com.samsung.microbit.utils.Utils; @@ -1200,7 +1201,17 @@ private void displayScreenTripleOrStep1( int resIdGif, int resIdPrompt) */ private void enableBluetooth() { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); - startActivityForResult(enableBtIntent, RequestCodes.REQUEST_ENABLE_BT); + int error = UIUtils.safelyStartActivityForResult( this, false, enableBtIntent, RequestCodes.REQUEST_ENABLE_BT); + if ( error != 0) { + //Change state back to Idle + setActivityState(PairingActivityState.STATE_IDLE); + PopUp.show( getString(R.string.this_device_may_have_restrictions_in_place), //message + getString(R.string.unable_to_start_activity_to_enable_bluetooth), + R.drawable.error_face, R.drawable.red_btn, + PopUp.GIFF_ANIMATION_ERROR, + PopUp.TYPE_ALERT, + failedPermissionHandler, failedPermissionHandler); + } } private void enableLocation() { @@ -1212,9 +1223,7 @@ private void enableLocation() { @Override public void onClick(View v) { PopUp.hide(); - //Unpair the device for secure BLE - Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); - startActivityForResult( intent, RequestCodes.REQUEST_ENABLE_LOCATION); + enableLocationOK(); } },//override click listener for ok button new View.OnClickListener() { @@ -1227,6 +1236,15 @@ public void onClick(View v) { }); } + private void enableLocationOK() { + Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); + int error = UIUtils.safelyStartActivityForResult( this, false, intent, RequestCodes.REQUEST_ENABLE_LOCATION); + if ( error != 0) { + setActivityState(PairingActivityState.STATE_IDLE); + popupLocationRestricted(); + } + } + public void popupLocationNeeded() { PopUp.show("Cannot continue without enabling location", //message "", @@ -1236,6 +1254,15 @@ public void popupLocationNeeded() { failedPermissionHandler, failedPermissionHandler); } + public void popupLocationRestricted() { + PopUp.show( getString(R.string.this_device_may_have_restrictions_in_place), //message + getString(R.string.unable_to_start_activity_to_enable_location_services), + R.drawable.error_face, R.drawable.red_btn, + PopUp.GIFF_ANIMATION_ERROR, + PopUp.TYPE_ALERT, + failedPermissionHandler, failedPermissionHandler); + } + @Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { diff --git a/app/src/main/java/com/samsung/microbit/ui/activity/ProjectActivity.java b/app/src/main/java/com/samsung/microbit/ui/activity/ProjectActivity.java index 3fce191b..d1548179 100644 --- a/app/src/main/java/com/samsung/microbit/ui/activity/ProjectActivity.java +++ b/app/src/main/java/com/samsung/microbit/ui/activity/ProjectActivity.java @@ -52,6 +52,7 @@ import com.samsung.microbit.service.PartialFlashingService; import com.samsung.microbit.ui.BluetoothChecker; import com.samsung.microbit.ui.PopUp; +import com.samsung.microbit.ui.UIUtils; import com.samsung.microbit.ui.adapter.ProjectAdapter; import com.samsung.microbit.ui.view.PatternDrawable; import com.samsung.microbit.utils.BLEConnectionHandler; @@ -1084,7 +1085,15 @@ private void proceedAfterBlePermissionGrantedAndBleEnabled() { @SuppressLint("MissingPermission") private void enableBluetooth() { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); - startActivityForResult(enableBtIntent, RequestCodes.REQUEST_ENABLE_BT); + int error = UIUtils.safelyStartActivityForResult( this, false, enableBtIntent, RequestCodes.REQUEST_ENABLE_BT); + if ( error != 0) { + PopUp.show( getString(R.string.this_device_may_have_restrictions_in_place), //message + getString(R.string.unable_to_start_activity_to_enable_bluetooth), + R.drawable.error_face, R.drawable.red_btn, + PopUp.GIFF_ANIMATION_ERROR, + TYPE_ALERT, + popupClickFlashComplete, popupClickFlashComplete); + } } private boolean havePermission(String permission) { @@ -2462,7 +2471,9 @@ private void scriptsImport() { intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.setType("application/octet-stream"); - startActivityForResult( Intent.createChooser(intent, messageTitle), REQUEST_CODE_IMPORT); + int error = UIUtils.safelyStartActivityForResult( this, true, Intent.createChooser(intent, messageTitle), REQUEST_CODE_IMPORT); + if ( error != 0) { + } } protected void onActivityResultScriptsImport(int requestCode, int resultCode, Intent data) { @@ -2482,7 +2493,9 @@ private void scriptsExport() { intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); intent.setType( mimetype); intent.putExtra(Intent.EXTRA_TITLE, name); - startActivityForResult( Intent.createChooser(intent, messageTitle), REQUEST_CODE_EXPORT); + int error = UIUtils.safelyStartActivityForResult( this, true, Intent.createChooser(intent, messageTitle), REQUEST_CODE_EXPORT); + if ( error != 0) { + } } protected void onActivityResultScriptsExport(int requestCode, int resultCode, Intent data) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5e6708aa..8e00f681 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -426,5 +426,9 @@ Out of memory Failed to create MY_DATA.HTM Works with micro:bit V2 only + "This device may have restrictions in place." + "Unable to enable Bluetooth" + "Unable to enable Location" + "Unable to start activity" + "Unable to open link" - From 1e9395542451e476109574783d0b055608436704 Mon Sep 17 00:00:00 2001 From: Martin Williams Date: Mon, 9 Sep 2024 16:47:13 +0100 Subject: [PATCH 2/5] External activity failure - change popups to toasts --- .../com/samsung/microbit/ui/FetchPopups.java | 15 +++-- .../java/com/samsung/microbit/ui/UIUtils.java | 57 +++++++++++++------ .../microbit/ui/activity/FetchActivity.java | 4 +- .../microbit/ui/activity/MakeCodeWebView.java | 6 +- .../microbit/ui/activity/PairingActivity.java | 29 ++++++---- .../microbit/ui/activity/ProjectActivity.java | 15 +++-- app/src/main/res/values/strings.xml | 8 +-- 7 files changed, 83 insertions(+), 51 deletions(-) diff --git a/app/src/main/java/com/samsung/microbit/ui/FetchPopups.java b/app/src/main/java/com/samsung/microbit/ui/FetchPopups.java index 6849634f..fd91e025 100644 --- a/app/src/main/java/com/samsung/microbit/ui/FetchPopups.java +++ b/app/src/main/java/com/samsung/microbit/ui/FetchPopups.java @@ -60,12 +60,15 @@ public void bluetoothOff() { } public void bluetoothEnableRestricted() { - PopUp.show( mClient.fetchPopupsContext().getString(R.string.this_device_may_have_restrictions_in_place), //message - mClient.fetchPopupsContext().getString(R.string.unable_to_start_activity_to_enable_bluetooth), - R.drawable.error_face, R.drawable.red_btn, - PopUp.GIFF_ANIMATION_ERROR, - PopUp.TYPE_ALERT, - popupClickActivityCancelled, popupClickActivityCancelled); + UIUtils.safelyStartActivityToast( mClient.fetchPopupsContext(), + mClient.fetchPopupsContext().getString(R.string.unable_to_start_activity_to_enable_bluetooth)); + mClient.fetchPopupsCancelled(); +// PopUp.show( mClient.fetchPopupsContext().getString(R.string.this_device_may_have_restrictions_in_place), //message +// mClient.fetchPopupsContext().getString(R.string.unable_to_start_activity_to_enable_bluetooth), +// R.drawable.error_face, R.drawable.red_btn, +// PopUp.GIFF_ANIMATION_ERROR, +// PopUp.TYPE_ALERT, +// popupClickActivityCancelled, popupClickActivityCancelled); } public void bluetoothConnectPermissionError() { diff --git a/app/src/main/java/com/samsung/microbit/ui/UIUtils.java b/app/src/main/java/com/samsung/microbit/ui/UIUtils.java index cfa51446..8c6e1fe7 100644 --- a/app/src/main/java/com/samsung/microbit/ui/UIUtils.java +++ b/app/src/main/java/com/samsung/microbit/ui/UIUtils.java @@ -19,6 +19,7 @@ import android.widget.Button; import android.widget.ImageButton; import android.widget.TextView; +import android.widget.Toast; import com.samsung.microbit.R; @@ -278,26 +279,42 @@ public void gifAnimate( @IdRes int id) { } } - public static void safelyStartActivityPopup( String message, String title) { - PopUp.show( message, title, - R.drawable.error_face, - R.drawable.red_btn, - PopUp.GIFF_ANIMATION_ERROR, - PopUp.TYPE_ALERT, - null, - null); +// public static void safelyStartActivityPopup( Context context, String message, String title) { +// PopUp.show( message, title, +// R.drawable.error_face, +// R.drawable.red_btn, +// PopUp.GIFF_ANIMATION_ERROR, +// PopUp.TYPE_ALERT, +// null, +// null); +// } +// +// public static void safelyStartActivityPopup( Context context, String title) { +// safelyStartActivityPopup( context, context.getString(R.string.this_device_may_have_restrictions_in_place), title); +// } +// +// public static void safelyStartActivityPopupGeneric( Context context) { +// safelyStartActivityPopup( context, context.getString(R.string.unable_to_start_activity)); +// } +// +// public static void safelyStartActivityPopupOpenLink( Context context) { +// safelyStartActivityPopup( context, context.getString(R.string.unable_to_open_link)); +// } + public static void safelyStartActivityToast( Context context, String message, String title) { + Toast.makeText( context, title + ".\n" + message, Toast.LENGTH_LONG).show(); } - public static void safelyStartActivityPopup( Context context, String title) { - safelyStartActivityPopup( context.getString(R.string.this_device_may_have_restrictions_in_place), title); + + public static void safelyStartActivityToast( Context context, String title) { + safelyStartActivityToast( context, context.getString(R.string.this_device_may_have_restrictions_in_place), title); } - public static void safelyStartActivityPopupGeneric( Context context) { - safelyStartActivityPopup( context, context.getString(R.string.unable_to_start_activity)); + public static void safelyStartActivityToastGeneric( Context context) { + safelyStartActivityToast( context, context.getString(R.string.unable_to_start_activity)); } - public static void safelyStartActivityPopupOpenLink( Context context) { - safelyStartActivityPopup( context, context.getString(R.string.unable_to_open_link)); + public static void safelyStartActivityToastOpenLink( Context context) { + safelyStartActivityToast( context, context.getString(R.string.unable_to_open_link)); } // Wrap startActivity and startActivityForResult @@ -307,6 +324,11 @@ public static void safelyStartActivityPopupOpenLink( Context context) { // needs to add code similar to the cancel case in onActivityResult public static int safelyStartActivity( Context context, boolean report, Intent intent, boolean forResult, int requestCode, Bundle options) { +// if ( report) { +// safelyStartActivityToastGeneric( context); +// } +// return 4; + int error = 0; ComponentName componentName = intent.resolveActivity( context.getPackageManager()); if ( componentName == null) { @@ -329,9 +351,8 @@ public static int safelyStartActivity( Context context, boolean report, Intent i error = 2; } } - if ( report && error != 0) - { - safelyStartActivityPopupGeneric( context); + if ( report && error != 0) { + safelyStartActivityToastGeneric( context); } return error; } @@ -357,7 +378,7 @@ public static int safelyStartActivityViewURI( Context context, boolean report, U intent.setData( uri); int error = UIUtils.safelyStartActivity( context, false, intent); if ( report && error != 0) { - safelyStartActivityPopupOpenLink( context); + safelyStartActivityToastOpenLink( context); } return error; } diff --git a/app/src/main/java/com/samsung/microbit/ui/activity/FetchActivity.java b/app/src/main/java/com/samsung/microbit/ui/activity/FetchActivity.java index d8454b89..9a01d7c0 100644 --- a/app/src/main/java/com/samsung/microbit/ui/activity/FetchActivity.java +++ b/app/src/main/java/com/samsung/microbit/ui/activity/FetchActivity.java @@ -945,7 +945,7 @@ public void onPageFinished(WebView view, String url) { mWebView.setWebChromeClient(new WebChromeClient() { @Override public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { - return onShowFileChooser( webView, filePathCallback, fileChooserParams); + return showFileChooser( webView, filePathCallback, fileChooserParams); } }); //setWebChromeClient @@ -979,7 +979,7 @@ public void onDownloadBase64( String base64, String mimetype) { } } - private boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { + private boolean showFileChooser(WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { mWebFileChooserCallback = filePathCallback; try { Intent intent = fileChooserParams.createIntent(); diff --git a/app/src/main/java/com/samsung/microbit/ui/activity/MakeCodeWebView.java b/app/src/main/java/com/samsung/microbit/ui/activity/MakeCodeWebView.java index 071f0029..a995861f 100644 --- a/app/src/main/java/com/samsung/microbit/ui/activity/MakeCodeWebView.java +++ b/app/src/main/java/com/samsung/microbit/ui/activity/MakeCodeWebView.java @@ -136,7 +136,7 @@ public void onPageFinished (WebView view, String url) { webView.setWebChromeClient(new WebChromeClient() { @Override public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { - return onShowFileChooser( webView, filePathCallback, fileChooserParams); + return showFileChooser( webView, filePathCallback, fileChooserParams); } }); //setWebChromeClient @@ -236,7 +236,7 @@ else if ( !hexName.isEmpty()) { openProjectActivity( hexToWrite); } else { Toast.makeText( MakeCodeWebView.this, - "Saved to FLASH page", Toast.LENGTH_LONG).show(); + "Saved to My Programs page", Toast.LENGTH_LONG).show(); } } } catch ( Exception e) { @@ -261,7 +261,7 @@ else if ( !hexName.isEmpty()) { } // onCreate - private boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { + private boolean showFileChooser(WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { onShowFileChooser_filePathCallback = filePathCallback; try { Intent intent = fileChooserParams.createIntent(); diff --git a/app/src/main/java/com/samsung/microbit/ui/activity/PairingActivity.java b/app/src/main/java/com/samsung/microbit/ui/activity/PairingActivity.java index 20ea2fe5..3412a681 100644 --- a/app/src/main/java/com/samsung/microbit/ui/activity/PairingActivity.java +++ b/app/src/main/java/com/samsung/microbit/ui/activity/PairingActivity.java @@ -1205,12 +1205,14 @@ private void enableBluetooth() { if ( error != 0) { //Change state back to Idle setActivityState(PairingActivityState.STATE_IDLE); - PopUp.show( getString(R.string.this_device_may_have_restrictions_in_place), //message - getString(R.string.unable_to_start_activity_to_enable_bluetooth), - R.drawable.error_face, R.drawable.red_btn, - PopUp.GIFF_ANIMATION_ERROR, - PopUp.TYPE_ALERT, - failedPermissionHandler, failedPermissionHandler); + UIUtils.safelyStartActivityToast( this, getString(R.string.unable_to_start_activity_to_enable_bluetooth)); + onFinish( RESULT_CANCELED); +// PopUp.show( getString(R.string.this_device_may_have_restrictions_in_place), //message +// getString(R.string.unable_to_start_activity_to_enable_bluetooth), +// R.drawable.error_face, R.drawable.red_btn, +// PopUp.GIFF_ANIMATION_ERROR, +// PopUp.TYPE_ALERT, +// failedPermissionHandler, failedPermissionHandler); } } @@ -1255,12 +1257,15 @@ public void popupLocationNeeded() { } public void popupLocationRestricted() { - PopUp.show( getString(R.string.this_device_may_have_restrictions_in_place), //message - getString(R.string.unable_to_start_activity_to_enable_location_services), - R.drawable.error_face, R.drawable.red_btn, - PopUp.GIFF_ANIMATION_ERROR, - PopUp.TYPE_ALERT, - failedPermissionHandler, failedPermissionHandler); + UIUtils.safelyStartActivityToast( this, + getString(R.string.unable_to_start_activity_to_enable_location_services)); + onFinish( RESULT_CANCELED); +// PopUp.show( getString(R.string.this_device_may_have_restrictions_in_place), //message +// getString(R.string.unable_to_start_activity_to_enable_location_services), +// R.drawable.error_face, R.drawable.red_btn, +// PopUp.GIFF_ANIMATION_ERROR, +// PopUp.TYPE_ALERT, +// failedPermissionHandler, failedPermissionHandler); } @Override diff --git a/app/src/main/java/com/samsung/microbit/ui/activity/ProjectActivity.java b/app/src/main/java/com/samsung/microbit/ui/activity/ProjectActivity.java index d1548179..a752f578 100644 --- a/app/src/main/java/com/samsung/microbit/ui/activity/ProjectActivity.java +++ b/app/src/main/java/com/samsung/microbit/ui/activity/ProjectActivity.java @@ -1087,12 +1087,15 @@ private void enableBluetooth() { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); int error = UIUtils.safelyStartActivityForResult( this, false, enableBtIntent, RequestCodes.REQUEST_ENABLE_BT); if ( error != 0) { - PopUp.show( getString(R.string.this_device_may_have_restrictions_in_place), //message - getString(R.string.unable_to_start_activity_to_enable_bluetooth), - R.drawable.error_face, R.drawable.red_btn, - PopUp.GIFF_ANIMATION_ERROR, - TYPE_ALERT, - popupClickFlashComplete, popupClickFlashComplete); + UIUtils.safelyStartActivityToast( this, + getString(R.string.unable_to_start_activity_to_enable_bluetooth)); + onFlashComplete(); +// PopUp.show( getString(R.string.this_device_may_have_restrictions_in_place), //message +// getString(R.string.unable_to_start_activity_to_enable_bluetooth), +// R.drawable.error_face, R.drawable.red_btn, +// PopUp.GIFF_ANIMATION_ERROR, +// TYPE_ALERT, +// popupClickFlashComplete, popupClickFlashComplete); } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8e00f681..c40d5350 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -426,9 +426,9 @@ Out of memory Failed to create MY_DATA.HTM Works with micro:bit V2 only - "This device may have restrictions in place." - "Unable to enable Bluetooth" - "Unable to enable Location" - "Unable to start activity" + "This device may be restricted." + "Unable to turn on Bluetooth" + "Unable to turn on Location" + "Unable to start external activity" "Unable to open link" From 590a415da3278bece8e1138165a3a5318a318379 Mon Sep 17 00:00:00 2001 From: Martin Williams Date: Thu, 12 Sep 2024 16:58:20 +0100 Subject: [PATCH 3/5] External activity failure - modify debug code --- app/src/main/java/com/samsung/microbit/ui/UIUtils.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/samsung/microbit/ui/UIUtils.java b/app/src/main/java/com/samsung/microbit/ui/UIUtils.java index 8c6e1fe7..13867ace 100644 --- a/app/src/main/java/com/samsung/microbit/ui/UIUtils.java +++ b/app/src/main/java/com/samsung/microbit/ui/UIUtils.java @@ -317,6 +317,8 @@ public static void safelyStartActivityToastOpenLink( Context context) { safelyStartActivityToast( context, context.getString(R.string.unable_to_open_link)); } +// public static boolean safelyStartActivityDebugFail = false; + // Wrap startActivity and startActivityForResult // Call resolveActivity and catch exception from startActivity // Return non-zero error on fail @@ -324,10 +326,12 @@ public static void safelyStartActivityToastOpenLink( Context context) { // needs to add code similar to the cancel case in onActivityResult public static int safelyStartActivity( Context context, boolean report, Intent intent, boolean forResult, int requestCode, Bundle options) { -// if ( report) { -// safelyStartActivityToastGeneric( context); +// if ( safelyStartActivityDebugFail) { +// if (report) { +// safelyStartActivityToastGeneric(context); +// } +// return 4; // } -// return 4; int error = 0; ComponentName componentName = intent.resolveActivity( context.getPackageManager()); From 8d9c464b9b34be04cada8ae4a467d40a2766da60 Mon Sep 17 00:00:00 2001 From: Martin Williams Date: Tue, 17 Sep 2024 11:43:07 +0100 Subject: [PATCH 4/5] External activity failure - ignore resolveActivity --- .../java/com/samsung/microbit/ui/UIUtils.java | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/samsung/microbit/ui/UIUtils.java b/app/src/main/java/com/samsung/microbit/ui/UIUtils.java index 13867ace..de9277d9 100644 --- a/app/src/main/java/com/samsung/microbit/ui/UIUtils.java +++ b/app/src/main/java/com/samsung/microbit/ui/UIUtils.java @@ -336,25 +336,29 @@ public static int safelyStartActivity( Context context, boolean report, Intent i int error = 0; ComponentName componentName = intent.resolveActivity( context.getPackageManager()); if ( componentName == null) { + /* TODO: Why is componentName null for + ACTION_CREATE_DOCUMENT (unless createChooser is used) + ACTION_VIEW? + */ Log.i(TAG,"startActivity - no component"); - error = 1; - } else { - try { - if ( forResult) { - if ( !(context instanceof Activity)) { - error = 3; - } else { - ((Activity) context).startActivityForResult(intent, requestCode, options); - } + } + + try { + if ( forResult) { + if ( !(context instanceof Activity)) { + error = 3; } else { - context.startActivity(intent); + ((Activity) context).startActivityForResult(intent, requestCode, options); } - } catch (Exception e) { - Log.i(TAG, "startActivity - exception"); - e.printStackTrace(); - error = 2; + } else { + context.startActivity(intent); } + } catch (Exception e) { + Log.i(TAG, "startActivity - exception"); + e.printStackTrace(); + error = 2; } + if ( report && error != 0) { safelyStartActivityToastGeneric( context); } From c24ef34137331ad1a0c8731ddf0c16bc3b34a780 Mon Sep 17 00:00:00 2001 From: Martin Williams Date: Thu, 19 Sep 2024 17:34:38 +0100 Subject: [PATCH 5/5] External activity failure - tidy up --- .../com/samsung/microbit/ui/FetchPopups.java | 6 ---- .../java/com/samsung/microbit/ui/UIUtils.java | 31 ------------------- .../microbit/ui/activity/PairingActivity.java | 12 ------- .../microbit/ui/activity/ProjectActivity.java | 6 ---- 4 files changed, 55 deletions(-) diff --git a/app/src/main/java/com/samsung/microbit/ui/FetchPopups.java b/app/src/main/java/com/samsung/microbit/ui/FetchPopups.java index fd91e025..5c1212b2 100644 --- a/app/src/main/java/com/samsung/microbit/ui/FetchPopups.java +++ b/app/src/main/java/com/samsung/microbit/ui/FetchPopups.java @@ -63,12 +63,6 @@ public void bluetoothEnableRestricted() { UIUtils.safelyStartActivityToast( mClient.fetchPopupsContext(), mClient.fetchPopupsContext().getString(R.string.unable_to_start_activity_to_enable_bluetooth)); mClient.fetchPopupsCancelled(); -// PopUp.show( mClient.fetchPopupsContext().getString(R.string.this_device_may_have_restrictions_in_place), //message -// mClient.fetchPopupsContext().getString(R.string.unable_to_start_activity_to_enable_bluetooth), -// R.drawable.error_face, R.drawable.red_btn, -// PopUp.GIFF_ANIMATION_ERROR, -// PopUp.TYPE_ALERT, -// popupClickActivityCancelled, popupClickActivityCancelled); } public void bluetoothConnectPermissionError() { diff --git a/app/src/main/java/com/samsung/microbit/ui/UIUtils.java b/app/src/main/java/com/samsung/microbit/ui/UIUtils.java index de9277d9..05f9ea0f 100644 --- a/app/src/main/java/com/samsung/microbit/ui/UIUtils.java +++ b/app/src/main/java/com/samsung/microbit/ui/UIUtils.java @@ -279,28 +279,6 @@ public void gifAnimate( @IdRes int id) { } } -// public static void safelyStartActivityPopup( Context context, String message, String title) { -// PopUp.show( message, title, -// R.drawable.error_face, -// R.drawable.red_btn, -// PopUp.GIFF_ANIMATION_ERROR, -// PopUp.TYPE_ALERT, -// null, -// null); -// } -// -// public static void safelyStartActivityPopup( Context context, String title) { -// safelyStartActivityPopup( context, context.getString(R.string.this_device_may_have_restrictions_in_place), title); -// } -// -// public static void safelyStartActivityPopupGeneric( Context context) { -// safelyStartActivityPopup( context, context.getString(R.string.unable_to_start_activity)); -// } -// -// public static void safelyStartActivityPopupOpenLink( Context context) { -// safelyStartActivityPopup( context, context.getString(R.string.unable_to_open_link)); -// } - public static void safelyStartActivityToast( Context context, String message, String title) { Toast.makeText( context, title + ".\n" + message, Toast.LENGTH_LONG).show(); } @@ -320,7 +298,6 @@ public static void safelyStartActivityToastOpenLink( Context context) { // public static boolean safelyStartActivityDebugFail = false; // Wrap startActivity and startActivityForResult - // Call resolveActivity and catch exception from startActivity // Return non-zero error on fail // When startActivityForResult fails, the caller likely // needs to add code similar to the cancel case in onActivityResult @@ -334,14 +311,6 @@ public static int safelyStartActivity( Context context, boolean report, Intent i // } int error = 0; - ComponentName componentName = intent.resolveActivity( context.getPackageManager()); - if ( componentName == null) { - /* TODO: Why is componentName null for - ACTION_CREATE_DOCUMENT (unless createChooser is used) - ACTION_VIEW? - */ - Log.i(TAG,"startActivity - no component"); - } try { if ( forResult) { diff --git a/app/src/main/java/com/samsung/microbit/ui/activity/PairingActivity.java b/app/src/main/java/com/samsung/microbit/ui/activity/PairingActivity.java index 3412a681..f37bc125 100644 --- a/app/src/main/java/com/samsung/microbit/ui/activity/PairingActivity.java +++ b/app/src/main/java/com/samsung/microbit/ui/activity/PairingActivity.java @@ -1207,12 +1207,6 @@ private void enableBluetooth() { setActivityState(PairingActivityState.STATE_IDLE); UIUtils.safelyStartActivityToast( this, getString(R.string.unable_to_start_activity_to_enable_bluetooth)); onFinish( RESULT_CANCELED); -// PopUp.show( getString(R.string.this_device_may_have_restrictions_in_place), //message -// getString(R.string.unable_to_start_activity_to_enable_bluetooth), -// R.drawable.error_face, R.drawable.red_btn, -// PopUp.GIFF_ANIMATION_ERROR, -// PopUp.TYPE_ALERT, -// failedPermissionHandler, failedPermissionHandler); } } @@ -1260,12 +1254,6 @@ public void popupLocationRestricted() { UIUtils.safelyStartActivityToast( this, getString(R.string.unable_to_start_activity_to_enable_location_services)); onFinish( RESULT_CANCELED); -// PopUp.show( getString(R.string.this_device_may_have_restrictions_in_place), //message -// getString(R.string.unable_to_start_activity_to_enable_location_services), -// R.drawable.error_face, R.drawable.red_btn, -// PopUp.GIFF_ANIMATION_ERROR, -// PopUp.TYPE_ALERT, -// failedPermissionHandler, failedPermissionHandler); } @Override diff --git a/app/src/main/java/com/samsung/microbit/ui/activity/ProjectActivity.java b/app/src/main/java/com/samsung/microbit/ui/activity/ProjectActivity.java index a752f578..2b1dd6df 100644 --- a/app/src/main/java/com/samsung/microbit/ui/activity/ProjectActivity.java +++ b/app/src/main/java/com/samsung/microbit/ui/activity/ProjectActivity.java @@ -1090,12 +1090,6 @@ private void enableBluetooth() { UIUtils.safelyStartActivityToast( this, getString(R.string.unable_to_start_activity_to_enable_bluetooth)); onFlashComplete(); -// PopUp.show( getString(R.string.this_device_may_have_restrictions_in_place), //message -// getString(R.string.unable_to_start_activity_to_enable_bluetooth), -// R.drawable.error_face, R.drawable.red_btn, -// PopUp.GIFF_ANIMATION_ERROR, -// TYPE_ALERT, -// popupClickFlashComplete, popupClickFlashComplete); } }