Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/quick_actions/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.3.2+2
* Fix bug that would make the shortcut not open on Android.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was it completely broken on Android or only in certain situations? I'd ideally like to test this plugin more but it will require a bit more progress on our Android testing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To reproduce the problem with the current master code.

  1. Open the app using the launcher.
  2. Exit the app using the Back button.
  3. Use the shortcut to open the app. ## There is no visual feedback of anything being done.

* Report shortcut used on Android.
* Improves example.

## 0.3.2+1

* Update usage example in README.
Expand Down
8 changes: 0 additions & 8 deletions packages/quick_actions/android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="io.flutter.plugins.quickactions">

<application>
<activity
android:name=".QuickActionsPlugin$ShortcutHandlerActivity"
android:exported="false"
android:relinquishTaskIdentity="true"
tools:targetApi="lollipop" />
</application>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@

package io.flutter.plugins.quickactions;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.content.res.Resources;
import android.graphics.drawable.Icon;
import android.os.Build;
import android.os.Bundle;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
Expand All @@ -23,17 +22,11 @@
import java.util.Map;

/** QuickActionsPlugin */
@SuppressWarnings("unchecked")
public class QuickActionsPlugin implements MethodCallHandler {
private final Registrar registrar;
private static final String intentExtraAction = "action";
private static String launchAction = null;
private static final String CHANNEL_ID = "plugins.flutter.io/quick_actions";
private static final String EXTRA_ACTION = "some unique action key";

// Channel is a static field because it needs to be accessible to the
// {@link ShortcutHandlerActivity} which has to be a static class with
// no-args constructor.
// It is also mutable because it is derived from {@link Registrar}.
private static MethodChannel channel;
private final Registrar registrar;

private QuickActionsPlugin(Registrar registrar) {
this.registrar = registrar;
Expand All @@ -45,13 +38,11 @@ private QuickActionsPlugin(Registrar registrar) {
* <p>Must be called when the application is created.
*/
public static void registerWith(Registrar registrar) {
channel = new MethodChannel(registrar.messenger(), "plugins.flutter.io/quick_actions");
final MethodChannel channel = new MethodChannel(registrar.messenger(), CHANNEL_ID);
channel.setMethodCallHandler(new QuickActionsPlugin(registrar));
launchAction = registrar.activity().getIntent().getStringExtra(intentExtraAction);
}

@Override
@SuppressLint("NewApi")
public void onMethodCall(MethodCall call, Result result) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) {
// We already know that this functionality does not work for anything
Expand All @@ -72,8 +63,13 @@ public void onMethodCall(MethodCall call, Result result) {
shortcutManager.removeAllDynamicShortcuts();
break;
case "getLaunchAction":
final Intent intent = registrar.activity().getIntent();
final String launchAction = intent.getStringExtra(EXTRA_ACTION);
if (launchAction != null && !launchAction.isEmpty()) {
shortcutManager.reportShortcutUsed(launchAction);
intent.removeExtra(EXTRA_ACTION);
}
result.success(launchAction);
launchAction = null;
return;
default:
result.notImplemented();
Expand All @@ -82,69 +78,56 @@ public void onMethodCall(MethodCall call, Result result) {
result.success(null);
}

@SuppressLint("NewApi")
@TargetApi(Build.VERSION_CODES.N_MR1)
private List<ShortcutInfo> deserializeShortcuts(List<Map<String, String>> shortcuts) {
List<ShortcutInfo> shortcutInfos = new ArrayList<>();
Context context = registrar.context();
final List<ShortcutInfo> shortcutInfos = new ArrayList<>();
final Context context = registrar.context();

for (Map<String, String> shortcut : shortcuts) {
String icon = shortcut.get("icon");
String type = shortcut.get("type");
String title = shortcut.get("localizedTitle");
ShortcutInfo.Builder shortcutBuilder = new ShortcutInfo.Builder(context, type);
if (icon != null) {
int resourceId =
context.getResources().getIdentifier(icon, "drawable", context.getPackageName());
if (resourceId > 0) {
shortcutBuilder.setIcon(Icon.createWithResource(context, resourceId));
}
final String icon = shortcut.get("icon");
final String type = shortcut.get("type");
final String title = shortcut.get("localizedTitle");
final ShortcutInfo.Builder shortcutBuilder = new ShortcutInfo.Builder(context, type);

final int resourceId = loadResourceId(context, icon);
final Intent intent = getIntentToOpenMainActivity(type);

if (resourceId > 0) {
shortcutBuilder.setIcon(Icon.createWithResource(context, resourceId));
}
shortcutBuilder.setLongLabel(title);
shortcutBuilder.setShortLabel(title);
Intent intent = new Intent(context, ShortcutHandlerActivity.class);
intent.setAction("plugins.flutter.io/quick_action");
intent.putExtra("type", type);
shortcutBuilder.setIntent(intent);
shortcutInfos.add(shortcutBuilder.build());

final ShortcutInfo shortcutInfo =
shortcutBuilder.setLongLabel(title).setShortLabel(title).setIntent(intent).build();
shortcutInfos.add(shortcutInfo);
}
return shortcutInfos;
}

/**
* Handle the shortcut and immediately closes the activity.
*
* <p>Needs to be invocable by Android system; hence it is public.
*/
public static class ShortcutHandlerActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get the Intent that started this activity and extract the string
Intent intent = getIntent();
String type = intent.getStringExtra("type");
if (channel != null) {
channel.invokeMethod("launch", type);
} else {
startActivity(getIntentToOpenMainActivity(this, type));
}
finish();
private int loadResourceId(Context context, String icon) {
if (icon == null) {
return 0;
}
final String packageName = context.getPackageName();
final Resources res = context.getResources();
final int resourceId = res.getIdentifier(icon, "drawable", packageName);

/**
* Returns Intent to launch the MainActivity. Used to start the app, if one of quick actions was
* called from the background.
*/
private Intent getIntentToOpenMainActivity(Context context, String type) {
Intent launchIntentForPackage =
context
.getPackageManager()
.getLaunchIntentForPackage(context.getApplicationContext().getPackageName());
if (launchIntentForPackage == null) {
return null;
} else {
launchIntentForPackage.putExtra(intentExtraAction, type);
return launchIntentForPackage;
}
if (resourceId == 0) {
return res.getIdentifier(icon, "mipmap", packageName);
} else {
return resourceId;
}
}

private Intent getIntentToOpenMainActivity(String type) {
final Context context = registrar.context();
final String packageName = context.getPackageName();

return context
.getPackageManager()
.getLaunchIntentForPackage(packageName)
.setAction(Intent.ACTION_RUN)
.putExtra(EXTRA_ACTION, type)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.flutter.plugins.quickactionsexample">
package="io.flutter.plugins.quickactionsexample">

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.INTERNET"/>

<application android:name="io.flutter.app.FlutterApplication" android:label="quick_actions_example" android:icon="@mipmap/ic_launcher">
<activity android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@android:style/Theme.Black.NoTitleBar"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
<application android:name="io.flutter.app.FlutterApplication"
android:label="quick_actions_example"
android:icon="@mipmap/ic_launcher">
<activity android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true"/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
android:height="108dp"
android:width="108dp"
android:viewportHeight="108"
android:viewportWidth="108"
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF2196F3"
android:pathData="M0,0h108v108h-108z"/>
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
</vector>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style
name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">@drawable/ic_launcher_background</item>
</style>
</resources>
Loading