Commit 1c5d0220 authored by zhouteng's avatar zhouteng

update project to support android embedding v2 api

parent b24c80ad
package com.zt.shareextend;
import androidx.annotation.NonNull;
import java.util.Map;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
/**
* Created by zhouteng on 2020/6/27
*/
public class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler {
private static final String METHOD_SHARE = "share";
private Share share;
public MethodCallHandlerImpl(Share share) {
this.share = share;
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
if (METHOD_SHARE.equals(call.method)) {
if (!(call.arguments instanceof Map)) {
throw new IllegalArgumentException("Map argument expected");
}
share.share(call);
result.success(null);
} else {
result.notImplemented();
}
}
}
package com.zt.shareextend;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import io.flutter.plugin.common.MethodCall;
/**
* Created by zhouteng on 2020/6/27
* <p>
* Handles share action
*/
public class Share {
private static final int CODE_ASK_PERMISSION = 100;
private Context context;
private MethodCall call;
public Share(Context context) {
this.context = context;
}
void share() {
share(call);
}
void share(MethodCall call) {
if (call == null) {
return;
}
this.call = call;
List<String> list = call.argument("list");
String type = call.argument("type");
String sharePanelTitle = call.argument("sharePanelTitle");
String subject = call.argument("subject");
String extraText = call.argument("extraText");
if (list == null || list.isEmpty()) {
throw new IllegalArgumentException("Non-empty list expected");
}
ArrayList<Uri> uriList = new ArrayList<>();
Intent shareIntent = new Intent();
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
shareIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
if ("text".equals(type)) {
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_TEXT, list.get(0));
shareIntent.setType("text/plain");
} else {
if (ShareUtils.shouldRequestPermission(list)) {
if (!checkPermission()) {
requestPermission();
return;
}
}
shareIntent.putExtra(Intent.EXTRA_TEXT, extraText);
for (String path : list) {
File f = new File(path);
Uri uri = ShareUtils.getUriForFile(context, f);
uriList.add(uri);
}
if ("image".equals(type)) {
shareIntent.setType("image/*");
} else if ("video".equals(type)) {
shareIntent.setType("video/*");
} else {
shareIntent.setType("application/*");
}
if (uriList.size() == 1) {
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, uriList.get(0));
} else {
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uriList);
}
}
startChooserActivity(shareIntent, sharePanelTitle, uriList);
}
private void startChooserActivity(Intent shareIntent, String sharePanelTitle, ArrayList<Uri> uriList) {
Intent chooserIntent = Intent.createChooser(shareIntent, sharePanelTitle);
ShareUtils.grantUriPermission(context, uriList, chooserIntent);
if (context instanceof Activity) {
context.startActivity(chooserIntent);
} else {
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(chooserIntent);
}
}
private boolean checkPermission() {
return ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED;
}
private void requestPermission() {
if (!(context instanceof Activity)) {
return;
}
ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, CODE_ASK_PERMISSION);
}
}
package com.zt.shareextend; package com.zt.shareextend;
import android.Manifest;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import java.io.File; import androidx.annotation.NonNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import androidx.core.app.ActivityCompat; import io.flutter.embedding.engine.plugins.FlutterPlugin;
import androidx.core.content.ContextCompat; import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry; import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.Registrar; import io.flutter.plugin.common.PluginRegistry.Registrar;
...@@ -23,125 +16,78 @@ import io.flutter.plugin.common.PluginRegistry.Registrar; ...@@ -23,125 +16,78 @@ import io.flutter.plugin.common.PluginRegistry.Registrar;
/** /**
* Plugin method host for presenting a share sheet via Intent * Plugin method host for presenting a share sheet via Intent
*/ */
public class ShareExtendPlugin implements MethodChannel.MethodCallHandler, PluginRegistry.RequestPermissionsResultListener { public class ShareExtendPlugin implements FlutterPlugin, ActivityAware, PluginRegistry.RequestPermissionsResultListener {
/// the authorities for FileProvider /// the authorities for FileProvider
private static final int CODE_ASK_PERMISSION = 100; private static final int CODE_ASK_PERMISSION = 100;
private static final String CHANNEL = "com.zt.shareextend/share_extend"; private static final String CHANNEL = "com.zt.shareextend/share_extend";
private final Registrar mRegistrar; private FlutterPluginBinding pluginBinding;
private List<String> list; private ActivityPluginBinding activityBinding;
private String type;
private String sharePanelTitle; private MethodChannel methodChannel;
private String subject; private MethodCallHandlerImpl callHandler;
private String extraText; private Share share;
public static void registerWith(Registrar registrar) { public static void registerWith(Registrar registrar) {
MethodChannel channel = new MethodChannel(registrar.messenger(), CHANNEL); ShareExtendPlugin plugin = new ShareExtendPlugin();
final ShareExtendPlugin instance = new ShareExtendPlugin(registrar); plugin.setUpChannel(registrar.context(), registrar.messenger(), registrar, null);
registrar.addRequestPermissionsResultListener(instance);
channel.setMethodCallHandler(instance);
} }
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
pluginBinding = flutterPluginBinding;
}
private ShareExtendPlugin(Registrar registrar) { @Override
this.mRegistrar = registrar; public void onDetachedFromEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
pluginBinding = null;
} }
@Override @Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) { public void onAttachedToActivity(@NonNull ActivityPluginBinding activityPluginBinding) {
if (call.method.equals("share")) { activityBinding = activityPluginBinding;
if (!(call.arguments instanceof Map)) { setUpChannel(activityBinding.getActivity(), pluginBinding.getBinaryMessenger(), null, activityBinding);
throw new IllegalArgumentException("Map argument expected");
}
// Android does not support showing the share sheet at a particular point on screen.
list = call.argument("list");
type = call.argument("type");
sharePanelTitle = call.argument("sharePanelTitle");
subject = call.argument("subject");
extraText = call.argument("extraText");
share(list, type, sharePanelTitle, subject, extraText);
result.success(null);
} else {
result.notImplemented();
}
} }
private void share(List<String> list, String type, String sharePanelTitle, String subject, String extraText) { @Override
ArrayList<Uri> uriList = new ArrayList<>();; public void onDetachedFromActivityForConfigChanges() {
onDetachedFromActivity();
}
if (list == null || list.isEmpty()) { @Override
throw new IllegalArgumentException("Non-empty list expected"); public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding activityPluginBinding) {
} onAttachedToActivity(activityPluginBinding);
Intent shareIntent = new Intent();
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
shareIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
if ("text".equals(type)) {
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_TEXT, list.get(0));
shareIntent.setType("text/plain");
} else {
if (ShareUtils.shouldRequestPermission(list)) {
if (!checkPermission()) {
requestPermission();
return;
}
}
shareIntent.putExtra(Intent.EXTRA_TEXT, extraText);
for (String path : list) {
File f = new File(path);
Uri uri = ShareUtils.getUriForFile(getContext(), f);
uriList.add(uri);
}
if ("image".equals(type)) {
shareIntent.setType("image/*");
} else if ("video".equals(type)) {
shareIntent.setType("video/*");
} else {
shareIntent.setType("application/*");
}
if (uriList.size() == 1) {
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, uriList.get(0));
} else {
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uriList);
}
}
startChooserActivity(shareIntent, sharePanelTitle, uriList);
} }
private Context getContext() { @Override
return mRegistrar.activity() != null ? mRegistrar.activity() : mRegistrar.context(); public void onDetachedFromActivity() {
tearDown();
} }
private void startChooserActivity(Intent shareIntent, String sharePanelTitle, ArrayList<Uri> uriList) { private void setUpChannel(Context context, BinaryMessenger messenger,Registrar registrar, ActivityPluginBinding activityBinding) {
Intent chooserIntent = Intent.createChooser(shareIntent, sharePanelTitle); methodChannel = new MethodChannel(messenger, CHANNEL);
ShareUtils.grantUriPermission(getContext(), uriList, chooserIntent); share = new Share(context);
callHandler = new MethodCallHandlerImpl(share);
if (mRegistrar.activity() != null) { methodChannel.setMethodCallHandler(callHandler);
mRegistrar.activity().startActivity(chooserIntent); if (registrar != null) {
registrar.addRequestPermissionsResultListener(this);
} else { } else {
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); activityBinding.addRequestPermissionsResultListener(this);
mRegistrar.context().startActivity(chooserIntent);
} }
} }
private boolean checkPermission() { private void tearDown() {
return ContextCompat.checkSelfPermission(mRegistrar.context(), Manifest.permission.WRITE_EXTERNAL_STORAGE) activityBinding.removeRequestPermissionsResultListener(this);
== PackageManager.PERMISSION_GRANTED; activityBinding = null;
} methodChannel.setMethodCallHandler(null);
methodChannel = null;
private void requestPermission() {
ActivityCompat.requestPermissions(mRegistrar.activity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, CODE_ASK_PERMISSION);
} }
@Override @Override
public boolean onRequestPermissionsResult(int requestCode, String[] perms, int[] grantResults) { public boolean onRequestPermissionsResult(int requestCode, String[] perms, int[] grantResults) {
if (requestCode == CODE_ASK_PERMISSION && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (requestCode == CODE_ASK_PERMISSION && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
share(list, type, sharePanelTitle, subject, extraText); share.share();
} }
return false; return false;
} }
......
...@@ -20,25 +20,40 @@ ...@@ -20,25 +20,40 @@
android:name="io.flutter.app.FlutterApplication" android:name="io.flutter.app.FlutterApplication"
android:label="share_extend_example" android:label="share_extend_example"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">
<activity <activity
android:name=".MainActivity" android:name="io.flutter.embedding.android.FlutterActivity"
android:launchMode="singleTop" android:launchMode="singleTop"
android:theme="@style/LaunchTheme" android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in @style/LaunchTheme). -->
<meta-data <meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame" android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:value="true" /> android:resource="@drawable/launch_background" />
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter> </intent-filter>
</activity> </activity>
<!-- used for v1 api -->
<activity
android:name=".EmbeddingV1Activity"
android:theme="@android:style/Theme.Black.NoTitleBar"
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" />
</activity>
<meta-data android:name="flutterEmbedding" android:value="2"/>
</application> </application>
</manifest> </manifest>
package com.zt.shareextendexample;
import android.os.Bundle;
import com.vitanov.multiimagepicker.MultiImagePickerPlugin;
import com.zt.shareextend.ShareExtendPlugin;
import io.flutter.app.FlutterActivity;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugins.flutter_plugin_android_lifecycle.FlutterAndroidLifecyclePlugin;
import io.flutter.plugins.imagepicker.ImagePickerPlugin;
import io.flutter.plugins.pathprovider.PathProviderPlugin;
public class EmbeddingV1Activity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ShareExtendPlugin.registerWith(registrarFor("com.zt.shareextend.ShareExtendPlugin"));
ImagePickerPlugin.registerWith(registrarFor("io.flutter.plugins.imagepicker.ImagePickerPlugin"));
MultiImagePickerPlugin.registerWith(registrarFor("com.vitanov.multiimagepicker.MultiImagePickerPlugin"));
PathProviderPlugin.registerWith(registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin"));
FlutterAndroidLifecyclePlugin.registerWith(registrarFor("io.flutter.plugins.flutter_plugin_android_lifecycle.FlutterAndroidLifecyclePlugin"));
}
}
package com.zt.shareextendexample;
import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
}
...@@ -18,9 +18,12 @@ dependencies: ...@@ -18,9 +18,12 @@ dependencies:
# The following section is specific to Flutter. # The following section is specific to Flutter.
flutter: flutter:
plugin: plugin:
androidPackage: com.zt.shareextend platforms:
pluginClass: ShareExtendPlugin android:
iosPrefix: FLT package: com.zt.shareextend
pluginClass: ShareExtendPlugin
ios:
pluginClass: FLTShareExtendPlugin
# To add assets to your plugin package, add an assets section, like this: # To add assets to your plugin package, add an assets section, like this:
# assets: # assets:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment