Android 运维技巧 系列目录
博客创建时间:2021.04.06
博客更新时间:2021.04.06
以Android studio build=4.1.3,gradle=6.5,SdkVersion 30来分析讲解。如图文和网上其他资料不一致,可能是别的资料版本较低而已
前言
App拉起另一个App的使用场景:
-
使用一个管理型App统一进行app的管理。如:可以应用于登录,然后拉起对应App,如未安装则进行安装。
-
对于智能硬件app,很多运行环境处于无网络情况,出现异常及崩溃后log无法采集,也无法重新现崩溃情景。此时应该先保持app崩溃后能重新自动重启。
此时可以用一看门狗app监测管理产品app,一旦发现软件App不在运行则拉起软件App,对于异常则后面专项检测解决。
今天主要讲解第2种情景中的app拉起。
分析及效果图
需求分析
- 看门狗App A实时监测软件App B的运行状态,其实是监测包名com.b…
- 如果B异常退出或被卸载,则A监测到B的运行状态异常,进行后续操作
- 如果B被卸载了,则提示进行下载安装
- 如果B已安装只是异常退出,则重新拉起B。
效果图
App拉起方式
常见的APP拉起方式有如下几种:
1. 根据包名、Activity名拉起
拉起的不一定是启动页,也有可能是其他Activity
/**
* 根据包名、Activit来拉起App
* 此方式拉起的App在原程序运行,不会再单独开启一个app应用
*
* @param activity 调用者Activity
* @param pkgName 包名
* @param acName 要拉起的Activity名,
*/
fun pullUpByPackage(activity: Activity, pkgName: String, acName: String) {
val intent = Intent(Intent.ACTION_MAIN)
// 知道要跳转应用的包命与目标Activity
val componentName = ComponentName(pkgName, acName)
intent.component = componentName
// 这里Intent传值
intent.putExtra("key", "value")
activity.startActivity(intent)
}
2. 仅根据包名拉起App
拉起的肯定是启动页
/**
* 仅仅通过包名进行调用,拉起的是启动页
* @param activity 调用者Activity
* @param pkgName 包名
*/
fun pullUpOnlyPackage(activity: Activity, pkgName: String) {
val intent: Intent? = activity.packageManager.getLaunchIntentForPackage(pkgName)
if (intent != null) {
intent.putExtra("type", "110")
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
activity.startActivity(intent)
}
}
3. 根据URL拉起App
/**
* 根据URL拉起App
*
*
* @param activity 调用者Activity
* @param uriString Uri地址 如 "csd://com.xuanyuan.pullup/cyn?type=110"
*
*/
fun pullUpByUri(activity: Activity, uriString: String) {
val intent = Intent()
intent.data = Uri.parse(uriString)
//这里Intent当然也可传递参数,但是一般情况下都会放到上面的URL中进行传递
intent.putExtra("type", "100")
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
activity.startActivity(intent)
}
根据Uri拉起的方式一定要注意,在manifest文件间需要配置如下,如果是在启动Activity中,则置于原有之下即可。
* <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>
对于要拉起的Activity需注意:
- manifest文件对应Activity 添加 android:exported=“true”
- 不添加exported="true"则无法找到该Activity
- intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK的设置与否,决定拉起的App是否在新进程中运行
拉起流程
- 对程序B进行检测,每隔固定时间如20s进行监测,不在前台运行则进行拉起。
Observable.interval(20, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
// .observeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
- 判定程序B是否已安装
/**
* 检查应用packageName 是否存在
*
* @return true:存在 ,false:不存在
*/
fun checkPackInfo(packageName: String, context: Context): Boolean {
var packageInfo: PackageInfo? = null
try {
packageInfo = context.packageManager.getPackageInfo(packageName, 0)
} catch (e: PackageManager.NameNotFoundException) {
e.printStackTrace()
}
return packageInfo != null
}
- 如果程序B不存在,进行下载操作提示
Toast.makeText(context, "需要拉起的软件还未安装,请先下载!", Toast.LENGTH_LONG).show()
- 如果程序B已安装,判断程序A是否是前台程序,如果是则说明程序B已异常退出,需要拉起B
val isForeground = isForeground(pkgContext)
pkgContext?.let {
isRun(it, pkgName) }
//3. 如果A正在前台运行,则说明程序B已经退出了
if (isForeground) {
//1. 启动方式1
return openPackage(context, pkgName)
总结
对于App A拉起App B的源码已发布在Github中,请下载查看。
程序A地址:Gitee或Github
程序B地址:Gitee或Github
相关链接:
博客书写不易,您的点赞收藏是我前进的动力,千万别忘记点赞、 收藏 ^ _ ^ !