AI智能
改变未来

Flutter和Android中的Intent

Flutter和Android中的Intent

  • 一、Android
  • (一)Activity
  • 1、显式Intent
  • 2、隐式Intent
  • 3、Intent的更多用法
  • (二)IntentService
    • 使用步骤
  • 二、Flutter
    • (一)路由与导航
    • (二)在Flutter中处理来自外部应用程序传入的Intents
    • (三)startActivityForResult
  • 三、部分参考资料

  • Intent 是一个消息传递对象,使用它可以向其他Android组件请求操作,其基本用途如:启动 Activity、启动服务、传递广播等。
    Flutter中虽然没有Intent的概念,但可以通过 Flutter的intent插件 来集成Intent的功能,其页面跳转等的实现也与Android的intent类似。
    最常见的就是点击按钮跳转页面的事件,下文中的Intent也可以添加在点击事件中查看效果,创建点击事件可以看这里。

    一、Android

    (一)Activity

    1、显式Intent

    (1)最简单常用的方式Intent intent = new Intent(this, SecondActivity.class);startActivity(intent);(2)setComponent()方法//第一个参数是被打开APP的包名,第二个参数是SecondActivity这个页面所在的全路径、也可以理解为包名+activity名ComponentName cName = new ComponentName(\"com.example.test\", \"com.example.test.SecondActivity\");Intent intent = new Intent();intent.setComponent(cName);//上述代码也可以是intent.setComponent(new ComponentName(\"com.example.test\",\"com.example.test.SecondActivity\"));startActivity(intent);(3)setClass()/setClassName()方法Intent intent = new Intent();intent.setClass(this, SecondActivity.class);//或者intent.setClassName(this, \"com.example.app.SecondActivity\");//或者intent.setClassName(this.getPackageName(),\"com.example.app.SecondActivity\");startActivity(intent);

    2、隐式Intent

    隐式Intent,即不明确指定启动哪个Activity,而是通过设置action、category、data等抽象信息,让系统来找出合适的Activity。

    (1)先在AndroidManifest.xml中找到你想要调用的Activity(被Intent调用的),然后添加或修改类似下列<intent-filter>的内容:<activityandroid:name=\"com.example.app.SecondActivity\"><intent-filter><action android:name=\"Second\"/>  //为了防止应用程序之间互相影响,一般的标准命名方式是包名+Action名,例如这里就应该改成\"com.example.test.SecondActivity\"。<category android:name=\"android.intent.category.DEFAULT\"/>  //至少必须要有这个category才能响应</intent-filter></activity>(2)Intent创建Intent intent = new Intent();intent.setAction(\"Second\");startActivity(intent);(3)每个Intent只能指定一个action,但却可以指定多个category,需要在上述(1)(2)的AndroidManifest.xml和Intent中修改如下:<activityandroid:name=\"com.example.app.SecondActivity\"><intent-filter><action android:name=\"Second\"/><category android:name=\"android.intent.category.DEFAULT\"/><category android:name=\"com.example.text.addcategory.ADD\"/></intent-filter></activity>Intent intent = new Intent();intent.setAction(\"Second\");intent.addCategory(\"com.example.text.addcategory.ADD\");startActivity(intent);

    3、Intent的更多用法

    Intent对象大致包括7个属性:Action(动作)、Category(类别)、Data(数据)、Type(数据类型)、Component(组件)、Extra(扩展信息)、Flag(标志位),可以用于在不同页面之间传递参数、调用手机系统内其他应用程序、打开网页等等很多功能。

    Activity的Action类型 作用
    ACTION_MAIN 表示程序入口
    ACTION_DAIL 跳转至拨号界面
    ACTION_CALL 直接拨号(需要先添加权限)
    Broadcast的Action类型 作用
    ACTION_TIME_TICK 当前时间改变,并即时发送时间,只能通过系统发送。调用格式\”android.intent.action.TIME_TICK\”
    ACTION_TIME_CHENGED 设置时间。调用格式\”android.intent.action.TIME_SET\”

    (更多属性的类型和用法可查看这里)

    (二)IntentService

    Service一般用于处理一些后台进程(不是线程)。IntentService则是继承并处理异步请求的一个类,可以看做Service和HandlerThread的结合体,在完成了使命之后会自动停止,适合需要在工作线程处理UI无关任务、后台耗时较多的场景。

    使用步骤

    1、自定义LocalIntentService继承自IntentService。
    2、实现onHandleIntent(), 用于实现任务逻辑。

    public class MyIntentService extends IntentService{public MyIntentService(String name) {super(name);}@Overrideprotected void onHandleIntent(@Nullable Intent intent) {String action = intent.getStringExtra(\"task_action\");Log.d(\"IntentService\", \"receive task :\" + action);SystemClock.sleep(2000); //即使第一个任务休眠,后续的任务也会等待其执行完毕再执行if(\"com.example.action.TASK1\".equals(action)){Log.d(\"IntentService\", \"handle task :\" + action);//运行时可以在控制台看到Log打印的日志}}}

    3、启动IntentService。

    Intent intentService = new Intent(this, MyIntentService.class);intentService.putExtra(\"tast_action\", \"com.example.action.TASK1\");startService(service);intentService.putExtra(\"tast_action\", \"com.example.action.TASK2\");startService(service);intnetService.putExtra(\"tast_action\", \"com.example.action.TASK3\");startService(service);

    二、Flutter

    Flutter不具有Intents的概念,但如果需要的话,Flutter可以通过Native整合来触发Intents,也可以集成Intent插件来调用外部组件。

    (一)路由与导航

    要在Flutter中切换屏幕,可以访问路由以绘制新的Widget。 管理多个屏幕有两个核心概念和类:Route 和 Navigator。Route是应用程序的“屏幕”或“页面”的抽象(可以认为是Activity), Navigator是管理Route的Widget。Navigator可以通过push和pop route以实现页面切换。

    和Android在AndroidManifest.xml中声明Activitiy类似,在Flutter中,可以将具有指定Route的Map传递到顶层MaterialApp实例:

    void main() {runApp(new MaterialApp(home: new MyAppHome(), // becomes the route named \'/\'routes: <String, WidgetBuilder> {\'/a\': (BuildContext context) => new MyPage(title: \'page A\'),\'/b\': (BuildContext context) => new MyPage(title: \'page B\'),\'/c\': (BuildContext context) => new MyPage(title: \'page C\'),},));}

    然后,就可以在需要的地方通过Navigator来切换到命名路由的页面:

    Navigator.of(context).pushNamed(\'/b\');

    (二)在Flutter中处理来自外部应用程序传入的Intents

    Flutter可以通过直接与Android层通信并请求共享的数据来处理来自Android的Intents。

    在这个例子中,我们注册文本共享intent,所以其他应用程序可以共享文本到我们的Flutter应用程序

    这个应用程序的基本流程是我们首先处理Android端的共享文本数据,然后等待Flutter请求数据,然后通过MethodChannel发送。

    首先像隐式Intent一样在AndroidManifest.xml中注册我们想要处理的intent:

    <activityandroid:name=\".MainActivity\"android:launchMode=\"singleTop\"android:theme=\"@style/LaunchTheme\"android:configChanges=\"orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection\"android:hardwareAccelerated=\"true\"android:windowSoftInputMode=\"adjustResize\"><!-- This keeps the window background of the activity showinguntil Flutter renders its first frame. It can be removed ifthere is no splash screen (such as the default splash screendefined in @style/LaunchTheme). --><!-- 这将保持活动的窗口背景显示直到Flutter呈现出它的第一帧。如果没有启动屏幕(例如默认启动屏幕在@style/LaunchTheme中定义)。 --><meta-dataandroid: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><intent-filter><action android:name=\"android.intent.action.SEND\" /><category android:name=\"android.intent.category.DEFAULT\" /><data android:mimeType=\"text/plain\" /></intent-filter></activity>

    然后,在MainActivity中处理intent,一旦我们从intent中获得共享文本数据,我们就会持有它,直到Flutter在完成准备就绪时请求它:

    package com.example.flutterintent;import android.content.Intent;import android.os.Bundle;import java.nio.ByteBuffer;import io.flutter.app.FlutterActivity;import io.flutter.plugin.common.ActivityLifecycleListener;import io.flutter.plugin.common.MethodCall;import io.flutter.plugin.common.MethodChannel;import io.flutter.plugins.GeneratedPluginRegistrant;public class MainActivity extends FlutterActivity {String sharedText;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);GeneratedPluginRegistrant.registerWith(this);Intent intent = getIntent();String action = intent.getAction();String type = intent.getType();if (Intent.ACTION_SEND.equals(action) && type != null) {if (\"text/plain\".equals(type)) {handleSendText(intent); // Handle text being sent}}new MethodChannel(getFlutterView(), \"app.channel.shared.data\").setMethodCallHandler(new MethodChannel.MethodCallHandler() {@Overridepublic void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {if (methodCall.method.contentEquals(\"getSharedText\")) {result.success(sharedText);sharedText = null;}}});}void handleSendText(Intent intent) {sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);}}

    最后,就可以在渲染Flutter视图时请求数据:

    import \'package:flutter/material.dart\';import \'package:flutter/services.dart\';void main() {runApp(new SampleApp());}class SampleApp extends StatelessWidget {// This widget is the root of your application.@overrideWidget build(BuildContext context) {return new MaterialApp(title: \'Sample Shared App Handler\',theme: new ThemeData(primarySwatch: Colors.blue,),home: new SampleAppPage(),);}}class SampleAppPage extends StatefulWidget {SampleAppPage({Key key}) : super(key: key);@override_SampleAppPageState createState() => new _SampleAppPageState();}class _SampleAppPageState extends State<SampleAppPage> {static const platform = const MethodChannel(\'app.channel.shared.data\');String dataShared = \"No data\";@overridevoid initState() {super.initState();getSharedText();}@overrideWidget build(BuildContext context) {return new Scaffold(body: new Center(child: new Text(dataShared)));}getSharedText() async {var sharedData = await platform.invokeMethod(\"getSharedText\");if (sharedData != null) {setState(() {dataShared = sharedData;});}}}

    (三)startActivityForResult

    在Android中,startActivityForResult用于启动一个Activity并获得它返回的数据,如打开本地文件选择器等。

    而处理Flutter中所有路由的Navigator类可用于从已经push到栈的路由中获取结果。 这可以通过等待push返回的Future来完成。例如,如果您要启动让用户选择其位置的位置的路由,则可以执行以下操作:

    Map coordinates = await Navigator.of(context).pushNamed(\'/location\');

    然后在你的位置路由中,一旦用户选择了他们的位置,你可以将结果”pop”出栈:

    Navigator.of(context).pop({\"lat\":43.821757,\"long\":-79.226392});

    三、部分参考资料

    文中不详尽之处还望指出补充✍
    Flutter中文网-Intent
    AndroidDeveloper官方文档
    Android Intent用法总结
    Android中Service与Intent的使用比较

    赞(0) 打赏
    未经允许不得转载:爱站程序员基地 » Flutter和Android中的Intent