Quick actions initial commit (#112) * Quick Actions plugin * Add licensing * Fix icon refs * Add licensing and fix usage based on engine update. * Add Android Support too. Update README * Remove more comments * Make analyzer and formatter happy * Review comments
diff --git a/packages/quick_actions/android/.gitignore b/packages/quick_actions/android/.gitignore new file mode 100644 index 0000000..5c4ef82 --- /dev/null +++ b/packages/quick_actions/android/.gitignore
@@ -0,0 +1,12 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures + +/gradle +/gradlew +/gradlew.bat
diff --git a/packages/quick_actions/android/build.gradle b/packages/quick_actions/android/build.gradle new file mode 100644 index 0000000..a66db47 --- /dev/null +++ b/packages/quick_actions/android/build.gradle
@@ -0,0 +1,32 @@ +group 'io.flutter.plugins.quickactions' +version '1.0-SNAPSHOT' + +buildscript { + repositories { + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:2.3.0' + } +} + +allprojects { + repositories { + jcenter() + } +} + +apply plugin: 'com.android.library' + +android { + compileSdkVersion 25 + buildToolsVersion '25.0.3' + + defaultConfig { + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + lintOptions { + disable 'InvalidPackage' + } +}
diff --git a/packages/quick_actions/android/gradle.properties b/packages/quick_actions/android/gradle.properties new file mode 100644 index 0000000..8bd86f6 --- /dev/null +++ b/packages/quick_actions/android/gradle.properties
@@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx1536M
diff --git a/packages/quick_actions/android/settings.gradle b/packages/quick_actions/android/settings.gradle new file mode 100644 index 0000000..7524824 --- /dev/null +++ b/packages/quick_actions/android/settings.gradle
@@ -0,0 +1 @@ +rootProject.name = 'quick_actions'
diff --git a/packages/quick_actions/android/src/main/AndroidManifest.xml b/packages/quick_actions/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000..7548f28 --- /dev/null +++ b/packages/quick_actions/android/src/main/AndroidManifest.xml
@@ -0,0 +1,10 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="io.flutter.plugins.quickactions" + android:versionCode="1" + android:versionName="0.0.1"> + + <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="25" /> + <application> + <activity android:name=".QuickActionsPlugin$ShortcutHandlerActivity" android:exported="false"/> + </application> +</manifest>
diff --git a/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java b/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java new file mode 100644 index 0000000..8e8b8dd --- /dev/null +++ b/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java
@@ -0,0 +1,118 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.quickactions; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ShortcutInfo; +import android.content.pm.ShortcutManager; +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; +import io.flutter.plugin.common.MethodChannel.Result; +import io.flutter.plugin.common.PluginRegistry.Registrar; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** QuickActionsPlugin */ +@SuppressWarnings("unchecked") +public class QuickActionsPlugin implements MethodCallHandler { + private final Activity activity; + // 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 QuickActionsPlugin(Activity activity) { + this.activity = activity; + } + + /** Plugin registration. */ + public static void registerWith(Registrar registrar) { + if (channel != null) { + throw new IllegalStateException("You should not call registerWith more than once."); + } + channel = new MethodChannel(registrar.messenger(), "plugins.flutter.io/quick_actions"); + channel.setMethodCallHandler(new QuickActionsPlugin(registrar.activity())); + } + + @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 + // lower than API 25 so we chose not to return error. Instead we do nothing. + result.success(null); + return; + } + ShortcutManager shortcutManager = + (ShortcutManager) activity.getSystemService(Context.SHORTCUT_SERVICE); + switch (call.method) { + case "setShortcutItems": + List<Map<String, String>> serializedShortcuts = call.arguments(); + List<ShortcutInfo> shortcuts = deserializeShortcuts(serializedShortcuts); + shortcutManager.setDynamicShortcuts(shortcuts); + break; + case "clearShortcutItems": + shortcutManager.removeAllDynamicShortcuts(); + break; + default: + result.notImplemented(); + return; + } + result.success(null); + } + + @SuppressLint("NewApi") + private List<ShortcutInfo> deserializeShortcuts(List<Map<String, String>> shortcuts) { + List<ShortcutInfo> shortcutInfos = new ArrayList<>(); + 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(activity, type); + if (icon != null) { + int resourceId = + activity.getResources().getIdentifier(icon, "drawable", activity.getPackageName()); + if (resourceId > 0) { + shortcutBuilder.setIcon(Icon.createWithResource(activity, resourceId)); + } + } + shortcutBuilder.setLongLabel(title); + shortcutBuilder.setShortLabel(title); + Intent intent = new Intent(activity, ShortcutHandlerActivity.class); + intent.setAction("plugins.flutter.io/quick_action"); + intent.putExtra("type", type); + shortcutBuilder.setIntent(intent); + shortcutInfos.add(shortcutBuilder.build()); + } + return shortcutInfos; + } + + /** + * Handle the shortcut and immediately closes the activity. + * + * <p>Needs to be invokable 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"); + channel.invokeMethod("launch", type); + finish(); + } + } +}