From 1560a79f4647da01a9a8b3c8c675025a51ee444b Mon Sep 17 00:00:00 2001 From: Jack Date: Tue, 28 May 2019 18:40:20 +0200 Subject: [PATCH] Added support to start specific Android Activity and added possibility to start atleast one of the available activities if it fails to find a launch activity Added 2 features in the app: 1. Added support to start specific Android Activity. 2. Added support to start other activity if launch activity is not found - this will make sure the plugin starts any activity available for the app, if it can't find a launch activity, helpful with "hidden apps" which don't have launcher intents, and are not visible in the default launcher --- README.md | 9 ++- .../AppAvailability.java | 56 ++++++++++++++++--- lib/flutter_appavailability.dart | 5 +- 3 files changed, 58 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index c42b74e..86ddf17 100755 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ First, add `flutter_appavailability` as a [dependency in your pubspec.yaml file] - `checkAvailability(String uri)` - `getInstalledApps()` (only for **Android**) - `isAppEnabled(String uri)` (only for **Android**) -- `launchApp(String uri)` +- `launchApp(String uri, String activity)` See the [docs](https://pub.dartlang.org/documentation/flutter_appavailability/latest/). @@ -132,6 +132,13 @@ class _MyAppState extends State { ``` +Example starting specific activity on Android. (this is useful if you want to start a specific activity of the app or the app doesn't have a launch intent and is not visible in a launcher) +```dart + +AppAvailability.launchApp('com.example.helloworld', 'com.example.helloworld.settings.main.SettingsActivity'); + +``` + Android: ![screenshot_1536780581](https://user-images.githubusercontent.com/5956938/45448682-48c49e80-b6d3-11e8-8e56-5972b017e233.png) diff --git a/android/src/main/java/com/pichillilorenzo/flutter_appavailability/AppAvailability.java b/android/src/main/java/com/pichillilorenzo/flutter_appavailability/AppAvailability.java index f6cb831..2bf242a 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_appavailability/AppAvailability.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_appavailability/AppAvailability.java @@ -14,6 +14,7 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.PackageInfo; import android.content.pm.ApplicationInfo; @@ -40,6 +41,7 @@ public static void registerWith(Registrar registrar) { @Override public void onMethodCall(MethodCall call, Result result) { String uriSchema; + String activityName; switch (call.method) { case "checkAvailability": uriSchema = call.argument("uri").toString(); @@ -54,7 +56,8 @@ public void onMethodCall(MethodCall call, Result result) { break; case "launchApp": uriSchema = call.argument("uri").toString(); - this.launchApp(uriSchema , result); + activityName = call.argument("activity").toString(); + this.launchApp(uriSchema, activityName, result); break; default: result.notImplemented(); @@ -127,19 +130,54 @@ private void isAppEnabled(String packageName, Result result) { } @TargetApi(Build.VERSION_CODES.CUPCAKE) - private void launchApp(String packageName, Result result) { - PackageInfo info = getAppPackageInfo(packageName); + private void launchApp(String packageName, String activityName, Result result) { - if(info != null) { - Intent launchIntent = registrar.context().getPackageManager().getLaunchIntentForPackage(packageName); - if (launchIntent != null) { - launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - registrar.context().startActivity(launchIntent); + //Start specific activity of the app + if(activityName != null){ + try { + launchActivity(packageName, activityName); result.success(null); - return; + } catch (Exception e) { + e.printStackTrace(); + } + } else { + PackageInfo info = getAppPackageInfo(packageName); + + if(info != null) { + Intent launchIntent = registrar.context().getPackageManager().getLaunchIntentForPackage(packageName); + if (launchIntent != null) { + launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + registrar.context().startActivity(launchIntent); + result.success(null); + return; + } + + //this will try to launch any available activity for the app if getLaunchIntentForPackage returns null, useful for launching apps without Launcher intent + if(info.activities != null){ + for (ActivityInfo activityInfo: + info.activities) { + try { + launchActivity(packageName, activityInfo.name); + result.success(null); + break; + } catch (Exception e) { + e.printStackTrace(); + } + } + return; + } } } result.error("", "App not found " + packageName, null); } + + @TargetApi(Build.VERSION_CODES.CUPCAKE) + private void launchActivity(String packageName, String activityName) { + Intent launchIntent = new Intent(Intent.ACTION_MAIN); + launchIntent.addCategory(Intent.CATEGORY_LAUNCHER); + launchIntent.setClassName(packageName, activityName); + launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + registrar.context().startActivity(launchIntent); + } } diff --git a/lib/flutter_appavailability.dart b/lib/flutter_appavailability.dart index 6c31c15..79613f7 100755 --- a/lib/flutter_appavailability.dart +++ b/lib/flutter_appavailability.dart @@ -85,13 +85,14 @@ class AppAvailability { return await _channel.invokeMethod("isAppEnabled", args); } - /// Launch an app with the given [uri] scheme if it exists. + /// Launch an app with the given [uri] scheme if it exists or if [activity] name is provided [android only]. /// /// If the app app isn't found, then a [PlatformException] is thrown. - static Future launchApp(String uri) async { + static Future launchApp(String uri, String activity) async { Map args = {}; args.putIfAbsent('uri', () => uri); if (Platform.isAndroid) { + args.putIfAbsent('activity', () => activity); await _channel.invokeMethod("launchApp", args); } else if (Platform.isIOS) {