作者:天一方蓝
一丶概述 前段时间配合开发,完成了一个APP拉起另一个APP的需求,负责接收数据跨登录部分。当然整个实现思路挺感兴趣就了解一下。先说说需求拉起另一个APP是为了方便统一使用管理,有些公司APP较多,部分人只需要用到部分APP,需要用到时就下载。市面上比较流行的解决办法,第一个就是现在说的新开发一个管理型APP,其他APP需要时再下载,运用时拉起,另一个就是插件化,直接将多个APP合成一个APP,这个感兴趣也可以了解一下。
二丶效果图 三丶需求分析 1.A点击拉起B;
2.如果B没安装,下载安装;
3.如果B已安转,未在后台运行点击打开B,传值账号密码,做跨登录;
4.如果B已安装,且正在后台运行,A打开B直接显示在后台运行的页面;
简版流程图:
四丶原理与实现 1.先说A拉起B可实现的几种方法
(1)包名,特定Activity名拉起
Intent intent = new Intent(Intent.ACTION_MAIN);/**知道要跳转应用的包命与目标Activity*/ ComponentName componentName = new ComponentName('kuyu.com.xxxx' , 'kuyu.com.xxxx.xxx.login.WelcomeActivity' ); intent.setComponent(componentName); intent.putExtra('' , '' );//这里Intent传值 startActivity(intent);
B应用需要在manifest文件对应Activity添加
android:exported='true'
(2)包名拉起(这里就是进去启动页)
Intent intent = getPackageManager().getLaunchIntentForPackage('kuyu.com.xxxx' );if (intent != null ) { intent.putExtra('type' , '110' ); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); }
(3)url拉起
Intent intent = new Intent(); intent.setData(Uri.parse('csd://pull.csd.demo/cyn?type=110' )); intent.putExtra('' , '' );//这里Intent当然也可传递参数,但是一般情况下都会放到上面的URL中进行传递 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);
B应用manifest文件需配置(注意:在原有intent-filter下方另外添加,不是在原先里面,两个同时存在)
intent-filter > data android:host ='pull.csd.demo' android:path ='/cyn' android:scheme ='csd' /> action android:name ='android.intent.action.VIEW' /> category android:name ='android.intent.category.DEFAULT' /> category android:name ='android.intent.category.BROWSABLE' />intent-filter >
优点:不暴露包命 缺点:host path schemeA应用和B应用得规定死
2.判断B应用是否安装
/** * 检查包是否存在 * * @param packname * @return */ private boolean checkPackInfo (String packname) { PackageInfo packageInfo = null ; try { packageInfo = getPackageManager().getPackageInfo(packname, 0 ); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return packageInfo != null ; }
3.判断B应用是否在后台运行并直接打开
public static Intent getAppOpenIntentByPackageName (Context context,String packageName) { //Activity完整名 String mainAct = null ; //根据包名寻找 PackageManager pkgMag = context.getPackageManager(); Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED|Intent.FLAG_ACTIVITY_NEW_TASK); List list = pkgMag.queryIntentActivities(intent, PackageManager.GET_ACTIVITIES); for (int i = 0 ; i < list.size();="" i++)=""> ResolveInfo info = list.get(i); if (info.activityInfo.packageName.equals(packageName)) { mainAct = info.activityInfo.name; break ; } } if (TextUtils.isEmpty(mainAct)) { return null ; } intent.setComponent(new ComponentName(packageName, mainAct)); return intent; }public static Context getPackageContext (Context context, String packageName) { Context pkgContext = null ; if (context.getPackageName().equals(packageName)) { pkgContext = context; } else { // 创建第三方应用的上下文环境 try { pkgContext = context.createPackageContext(packageName, Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } } return pkgContext; }public static boolean openPackage (Context context, String packageName) { Context pkgContext = getPackageContext(context, packageName); Intent intent = getAppOpenIntentByPackageName(context, packageName); if (pkgContext != null && intent != null ) { pkgContext.startActivity(intent); return true ; } return false ; }if (checkPackInfo('kuyu.com.xxxxx' )) { openPackage(this ,'kuyu.com.xxxxx' ); } else { Toast.makeText(this , '没有安装' + '' ,Toast.LENGTH_LONG).show(); //TODO 下载操作 }
这里运用的是模拟点击图标启动,不会出现程序多开,和栈顶Activity重复或者顺序错乱的问题。 当然Activity的LaunchMode最好设为“singletop”
4.B应用接受传值跨登录操作
一般启动页有几种操作
(1)定时直接跳转登录页面
这个就简单了,直接在handle发送跳转做判断接收intent操作就可以了
例:
if (getIntent().hasExtra('xxxx' )){ otherOpen(); }else { mHandler.removeMessages(0 ); mHandler.sendEmptyMessageDelayed(0 , 3000 ); }
(2)做了用户信息保存,跳过登录的,这个时候就通过handle的消息判断,做出相应操作
例:
/** * 跳去首页/登录页面 */ Handler handler = new Handler() { @Override public void handleMessage (Message msg) { switch (msg.arg1) { case 1009 : goToActivity(MainActivity.class); WelcomeActivity.this .finish(); break ; case 1010 : gotoLogin(handler1, runnable); break ; } } };
五丶参考文章 Android从一个APP跳转到另一个APP的主界面或某页面,并传递数据 Android-跳转第三方app重复启动问题 通过 PackageManager 获得你想要的 App 信息