Android跨应用启动实例详解

Android跨应用启动实例详解,第1张

概述Android跨应用启动前言:相信大家,很多时候都是在自己的应用中,启动自己写的Activity,Service、BroadcastReceiver、contentProvider。换句话说,这些都只是*单个应用中组件间*的启动。而我们下面要谈论的是两个

AndroID跨应用启动

前言:

相信大家,很多时候都是在自己的应用中,启动自己写的Activity,Service、broadcastReceiver、contentProvIDer 。换句话说,这些都只是 * 单个应用中 组件间 * 的启动。而我们下面要谈论的是 两个应用间 组件 的启动。即――使用 隐式Intent方式 启动应用B的某个组件。

一、在开始之前,先来梳理一下跨应用启动的2种方式:

第一种:在Activity中,启动另一个app的组件。

第二种:在Service中,启动另一个app的组件。

从所周知,AndroID中有四大组件,那么为什么小编,只介绍Activity和Service中启动另一个应用的四大组件?

其实,broadcastReceiver组件也是可以启动 4大组件的。这是因为onReceive()方法中会要求传入context实例,有了context实例,就能使用context的方法,启动其他组件。

至于contentProvIDer,我想大家还没见过,这娃自动去干过事情吧,都是被动的调用。

所以在写代码的时候,我们经常会在Activity或者Service中去启动一个组件,broadcastReceiver很少,而contentProvIDer更是没见过。

另外需要跟大家说一下,Context类是一个抽象类,传入的context实例是由其子类来实现的,这种――用父类声明变量,由子类来实现的思维方式,在Java中是很常见的。特别是接口和抽象类,经常用到这种方式。对于小编这种由C转Java的人来说,真是一大坑啊。

为什么Activity和Service都可以直接使用图中的四个方法呢,这是因为Activity和Service都是继承自Contextwrapper,所以子类拥有父类的方法。broadcastReceiver和contentProvIDer则不是,具体大家可以看官方API。

二、跨应用启动的实战

** 下面让我们正式进入今天的主题:跨应用启动实战**

1:AppA的Activity中,启动AppB的Activity

AndroID提供了在一个App中启动另一个App中的Activity的能力,这使我们的程序很容易就可以调用其他程序的功能,从而就丰富了我们App的功能。比如在微信中发送一个位置信息,对方可以点击这个位置信息启动腾讯地图并导航。这个场景在现实中作用很大,尤其是朋友在陌生的环境找不到对方时,这个功能简直就是救星。

本来想把本文的名字叫启动另一个进程中的Activity,觉得这样才有逼格。因为每个App都会运行在自己的虚拟机中,每个虚拟机跑在一个进程中。但仔细一想,能够称为一个进程,前提是这个App必须要运行起来才行。而AndroID提供的能力,是不需要另一个App启动就可以将其特定的Activity启动起来的。

也就是说B应用是处理未启动的状态,也就是还没有成为系统的一个进程,那么当使用A启动B应用的某个组件时,请问,B应用是否成为系统的进程?答案是yes。怎么看呢,可以从AndroID Studio 的AndroID device monito 中结合虚拟机看。

我们有至少两种办法达到启动另一个App中的Activity。

第一种―――隐式Intent的action方式。

相信这种方式,大家都不会陌生。这里就不进行过多的解析。这里只贴一下AppB的manifest(文件清单):

从文件清单中,我们可以看到,appB中有两个Activity。其中SecondActivity就是要被appA启动的Activity。
那么我们只要在appA的任意一个组件(Activity或Service),做如下的调用:

Intent intent=new Intent("androID.intent.action.SecondActivity");startActivity(intent);

就可以成功在 A应用中 启动B应用的 组件。另外还要跟大家说一点,SecondActivity的category一定要在文件清单中添加上,否则启动的时候会报错的。

不知道大家有没有思考过这三个事情: 1、当A应用 启动 B应用的SecondActivity,那么B应用的MainActivity会不会被启动呢?正常情况下,我们点击应用B,进到的是MainActivity这个活动,那么现在我们是通过跨应用启动,会不会要经过B的MainActivity呢?答案是不会。2、当我们在SecondActivity中点击Back回退键时,回到的是A应用的mainActivity界面,这里时候大家有没有想过。 SecondActivity和appA的mainActivity是不是同处于一个栈中呢?这时候就要去打印栈的ID了。3、由上面的两件事,不知道大家想起:AndroID对于Activity的管理,也就是framework层的ActivityManager。也就是说,你手机上的N多应用,当你打开某一个应用是,这个应用的Activity都是由ActivityManager这娃来创建和管理的。应用本身并没有创建Activity的能力。当然这其中又涉及到了Ibinder的通讯。这里暂时不讲。
 

第二种用intent设置classname或component的办法启动。举例如下。

新建两个项目ProjectA和ProjectB,用B中的MainActivity启动A的MainActivitity。关键代码如下:

ProjectA MainActivity

@OverrIDe public voID onClick(VIEw v) { Intent intent = new Intent(Intent.ACTION_VIEW); String packagename = "com.example.mylife.anotherapp"; String classname = "com.example.mylife.anotherapp.MainActivity"; intent.setClassname(packagename,classname); //second method //intent.setComponent(new Componentname("com.example.mylife.anotherapp","com.example.mylife.anotherapp.MainActivity")); Bundle bundle = new Bundle(); bundle.putString("msg","this message is from project B "); intent.putExtras(bundle); intent.putExtra("pID",androID.os.Process.myPID()); startActivityForResult(intent,1); //startActivity(intent); } @OverrIDe protected voID onActivityResult(int requestCode,int resultCode,Intent data) { super.onActivityResult(requestCode,resultCode,data); switch (requestCode) { case 1: if(resultCode == RESulT_OK) { textVIEw.setText(data.getStringExtra("result")); } break; } }

ProjectB MainActivity

 @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.activity_main); textVIEw = (TextVIEw)findVIEwByID(R.ID.text); Intent intent = getIntent(); if(intent != null) { textVIEw.setText(intent.getStringExtra("msg")); } } public voID OnClick(VIEw vIEw) { Intent intent = new Intent(); intent.putExtra("result","OK! from project a."); this.setResult(RESulT_OK,intent); this.finish();//要清楚这里为什么要用finish()。 }

注意:如果在应用B中,是通过按下Back键,回退到应用A的MainActivity活动,那么A的onActivityResult()方法是不会被回调的,这是因为ProjectB的MainActivity活动只是出栈而已,并没有销毁。而只有ProjectB的MainActivity活动被销毁的时候,才会回调A的onActivityResult()方法。那如果是按了Back键回退的话怎么处理呢?这时候只要重写appB的onBackpressed()方法就好了。

@OverrIDepublic voID onBackpressed() { super.onBackpressed(); Intent intent = new Intent(); intent.putExtra("result",intent); this.finish();//要清楚这里为什么要用finish()。}

二:进阶―――在A应用的Activity中启动(停止)――B应用的服务

应用B的manifest

应用B的service的代码:

public class MyService extends Service { private static final String TAG = "MyService"; public MyService() { } @OverrIDe public IBinder onBind(Intent intent) { // Todo: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @OverrIDe public voID onCreate() { super.onCreate(); Log.d(TAG,"onCreate: "); } @OverrIDe public int onStartCommand(Intent intent,int flags,int startID) { Log.d(TAG,"onStartCommand: "); if(intent != null) { Log.d(TAG,"onStartCommand: "+intent.getStringExtra("msg")); } return super.onStartCommand(intent,flags,startID); } @OverrIDe public voID onDestroy() { super.onDestroy(); Log.d(TAG,"onDestroy: "); } }

应用A的代码:

@OverrIDe public voID onClick(VIEw v) { Intent intent = new Intent(Intent.ACTION_VIEW); String packagename = "com.example.mylife.anotherapp"; String classname = "com.example.mylife.anotherapp.MyService"; intent.setClassname(packagename,classname); switch (v.getID()) { case R.ID.btn_start: Bundle bundle = new Bundle(); bundle.putString("msg",androID.os.Process.myPID()); startService(intent); break; case R.ID.btn_stop: stopService(intent); break; } }

测试结果:A应用直接启动B应用的服务,而B应用并不会打开自己的Activity。

本次代码参考:https://www.oudahe.com/p/25567/

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

总结

以上是内存溢出为你收集整理的Android跨应用启动实例详解全部内容,希望文章能够帮你解决Android跨应用启动实例详解所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1146344.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存