从第三方启动另一个APP

一、Android在一个APP中通过包名或类名启动另一个APP

开发有时需要在一个应用中启动另一个应用,比如Launcher加载所有的已安装的程序的列表,当点击图标时可以启动另一个应用。一般我们知道了另一个应用的包名和MainActivity的名字之后便可以直接通过如下代码来启动:

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);            
ComponentName cn = new ComponentName(packageName, className);            
intent.setComponent(cn);
startActivity(intent);

或者

  1. /** 
  2.  * 启动一个app 
  3.  * com -- ComponentName 对象,包含apk的包名和主Activity名 
  4.  * param -- 需要传给apk的参数 
  5.  */  
  6. private void startApp(ComponentName com, String param) {  
  7.     if (com != null) {  
  8.         PackageInfo packageInfo;  
  9.         try {  
  10.             packageInfo = getPackageManager().getPackageInfo(com.getPackageName(), 0);  
  11.         } catch (NameNotFoundException e) {  
  12.             packageInfo = null;  
  13.             Toast.makeText(this, "没有安装", Toast.LENGTH_SHORT).show();  
  14.             e.printStackTrace();  
  15.         }  
  16.         try {  
  17.             Intent intent = new Intent();  
  18.             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  19.             intent.setComponent(com);  
  20.             if (param != null) {  
  21.                 Bundle bundle = new Bundle(); // 创建Bundle对象  
  22.                 bundle.putString("flag", param); // 装入数据  
  23.                 intent.putExtras(bundle); // 把Bundle塞入Intent里面  
  24.             }  
  25.             startActivity(intent);  
  26.         } catch (Exception e) {  
  27.             Toast.makeText(this, "启动异常", Toast.LENGTH_SHORT).show();  
  28.         }  
  29.     }  
  30. }  

但是更多的时候,我们一般都不知道目标应用程序的启动Activity的类名,而只知道包名,接下来就需要这么做了,我封装成了一个方法,如下所示:

  1.  /* 
  2.  * 启动一个app 
  3.  */  
  4. public void startAPP(String appPackageName){  
  5.     try{  
  6.         Intent intent = this.getPackageManager().getLaunchIntentForPackage(appPackageName);  
  7.         startActivity(intent);  
  8.     }catch(Exception e){  
  9.         Toast.makeText(this, "没有安装", Toast.LENGTH_LONG).show();  
  10.     }  
  11. }  
  12.  

    或者

private void doStartApplicationWithPackageName(String packagename) {
 
        // 通过包名获取此APP详细信息,包括Activities、services、versioncode、name等等
        PackageInfo packageinfo = null;
        try {
            packageinfo = getPackageManager().getPackageInfo(packagename, 0);
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        if (packageinfo == null) {
            return;
        }
 
        // 创建一个类别为CATEGORY_LAUNCHER的该包名的Intent
        Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
        resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        resolveIntent.setPackage(packageinfo.packageName);
 
        // 通过getPackageManager()的queryIntentActivities方法遍历
        List<ResolveInfo> resolveinfoList = getPackageManager()
                .queryIntentActivities(resolveIntent, 0);
 
        ResolveInfo resolveinfo = resolveinfoList.iterator().next();
        if (resolveinfo != null) {
            // packagename = 参数packname
            String packageName = resolveinfo.activityInfo.packageName;
            // 这个就是我们要找的该APP的LAUNCHER的Activity[组织形式:packagename.mainActivityname]
            String className = resolveinfo.activityInfo.name;
            // LAUNCHER Intent
            Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_LAUNCHER);
 
            // 设置ComponentName参数1:packagename参数2:MainActivity路径
            ComponentName cn = new ComponentName(packageName, className);
 
            intent.setComponent(cn);
            startActivity(intent);
        }
    }

二、利用URL Scheme打开APP并传递数据

利用外部链接打开APP并传递一些附带信息是现在很多APP都有的功能,我在这把这部分的知识记录一下。

1、什么是URL Scheme?

android中的scheme是一种页面内跳转协议,是一种非常好的机制,通过自己在AndroidManifest.xml文件里面定义自己的scheme协议,可以非常方便的跳转到App的各个页面。通过scheme协议,甚至可以跳转到App的某个页面,可以通过直接输入URL进行跳转,也可以把URL写进HTML页面进行跳转。

2、实现的大致流程

我们手机的APP可以向操作系统注册一个URL Scheme,该scheme用于从浏览器或其他应用中启动本应用。

3、URL Scheme的协议格式

tlqp://my.app/openwith?roomID=123456

scheme:tlqp 代表Scheme的协议名称(必须)

host:my.app 代表host

path:openwith 代表path

query:roomID=123456 代表URL传递的值

4、设置URL Scheme


<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.VIEW"/>    
    <category android:name="android.intent.category.DEFAULT" />    
    <category android:name="android.intent.category.BROWSABLE" />    
    <data android:scheme="tlqp" android:host="my.app" android:pathPrefix="/openwith" />    
</intent-filter>
在AndroidManifest.xml文件,添加以上代码(根据情况适当修改),这里需要注意的地方是,不能再上面的Intent-filter里面添加相关代码,因为那里面存在MAIN和LAUNCHER相关代码,混在一起的话,会造成App图标丢失的情况。需要新建一个intent-filter,然后把代码添加进去即可。


5、获取URL附带的参数


Uri uri = getIntent().getData();
if (uri != null) {
    // 完整的url信息
    String url = uri.toString();
    Log.e(TAG, "url: " + uri);
    // scheme部分
    String scheme = uri.getScheme();
    Log.e(TAG, "scheme: " + scheme);
    // host部分
    String host = uri.getHost();
    Log.e(TAG, "host: " + host);
    //port部分
    int port = uri.getPort();
    Log.e(TAG, "host: " + port);
    // 访问路劲
    String path = uri.getPath();
    Log.e(TAG, "path: " + path);
    List<String> pathSegments = uri.getPathSegments();
    // Query部分
    String query = uri.getQuery();
    Log.e(TAG, "query: " + query);
    //获取指定参数值
    String goodsId = uri.getQueryParameter("goodsId");
    Log.e(TAG, "goodsId: " + goodsId);
}


6、打开app的方式

可以把URL写进HTML里面通过点击网页链接打开APP


<html>
 
    <head>
 
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    
        <title>Insert title here</title>
 
    </head>
 
    <body>
 
        <a href="tlqp://my.app/openwith?roomID=203518">打开app</a><br/>
 
    </body>
 
</html>

三、

补充:点击链接启动APP及Android App Links详解

首先,来看看android中的两类链接: 
  1、深链接Deep linking 
    深链接即我们通常说的scheme跳转,需要我们在清单文件中对activity添加intent-fillter,并定义scheme(包括但不限于HTTP协议)。如果用户手机内安装了多款能响应链接启动的应用,那么系统会弹出一个选择器,让用户自主选择用哪个应用打开(可能不是你的应用)。 
  2、安卓软件链接组 Android App Links 
    Android App Links是6.0以后才支持的链接方式,APP通过定义一组你自有的HTTP URL将该其设置为系统的默认打开对应域名的地址的应用(注意区分:不是6.0以下的默认打开某类数据)。当用户点击了包含你的域名的链接时,系统默认用你的APP打开该链接,如果用户手机未安装你的APP,那么会直接用浏览器打开。手机里的其他应用则不能打开。 
  3、Deep linking和App Links区别一览图

区别项    Deep lingking    App Links
Intent URL scheme    http,https,自定义协议    http,https
Intent action    任何action    需要android.intent.action.VIEW
Intent category    任何category    需要android.intent.category.BROWSABLE和android.intent.category.DEFAULT
链接验证    不验证    通过DAL文件和https验证
用户体验    可能会弹出一个APP选择弹框让用户选择用哪个应用打开    不弹APP选择弹框,直接用你的APP打开(已安装,否则直接打开网页)
兼容性    所有版本系统    6.0及以上
  因此,Android App Links相对于Deep linking有以下几点优势: 
  1、安全:因为只有你自己的APP能打开,所以很可靠; 
  2、无缝的用户体验:因为只有自己的APP可以打开,所以不会出现让用户选择哪个应用的打开的弹框,如果用户没有安装你的APP,则直接用浏览器打开。 
  3、支持免安装的谷歌应用:当然,这条优势对国内开发者来说没什么影响,因为谷歌的免安装应用需要上传到google player。 
  4、支持从浏览器、谷歌搜索APP、手机快捷搜索和谷歌助手等多个地方通过链接启动APP。 
   
  Deep linking支持: 
  当用户点击一个链接时,系统默认按以下顺序打开: 
  1、如果你设置了默认打开应用,则优先使用该应用打开; 
  2、如果只有一个应用能打开,则直接用该应用打开; 
  3、如果有多个应用能打开,才会弹出应用选择弹框。 
   
  以下就是一个支持Deep linking启动的activity的意图配置模板,注意看注释:

<activity android:name=".SecondActivity">
            <intent-filter>
                <!--必须的action-->
                <action android:name="android.intent.action.VIEW"/>
                <!--必须的category-->
                <category android:name="android.intent.category.DEFAULT"/>
                <!--必须的category-->
                <category android:name="android.intent.category.BROWSABLE"/>
                <!--支持以"http://www.jack_bear_csdn.com"开始的uri打开-->
                <data android:host="www.jack_bear_csdn.com" android:scheme="http"/>
            </intent-filter>

            <intent-filter>
                <!--必须的action-->
                <action android:name="android.intent.action.VIEW"/>
                <!--必须的category-->
                <category android:name="android.intent.category.DEFAULT"/>
                <!--必须的category-->
                <category android:name="android.intent.category.BROWSABLE"/>
                <!--支持以"jackxiong://www.jack_bear_csdn.com"开始的uri打开-->
                <data android:host="www.jack_bear_csdn.com" android:scheme="jackxiong"/>
            </intent-filter>

        </activity>
  通过ADB命令检测是否配置正确 
  如果通过以下命令能够打开目标activity,则说明我们的配置无误: 
   adb shell am start 
  -W -a android.intent.action.VIEW 
   -d < 你配置的Uri> < 你的APP包名>

  根据我上面的配置代码,那么我的adb命令对应如下图: 
  
  从上图中可以看出,通过以 http://和jackxiong://开头的协议启动目标activity的命令均Complete了,说明配置是正确的。 
   
  Android App Links支持 
  Android App Links也免不了需要在清单文件里为activity声明意图过滤器,只不过它声明的是一个可用的url,如果你的android studio是2.3以上的版本,而且你也不想自己写intent-filter部分的代码,我们可以通过android studio的APP链接助手来实现半自动的为目标activity添加intent-filter: 
  1、点击Tools选择App Links Assistant打开助手面板 
  
  2、点击助手面板中的Open URL Mapping Editor按钮打开activity和url映射配置的操作面板 
  
  从上图中我们可以看到,当我们打开这个操作面板时: 
  区域1:会默认显示我们APP中所有声明了url意图过滤器的activity及其对应的url详情; 
  区域4:当我们在区域1中选中了某天映射时,该activity及其intent-filter在清单文件中的代码可以在区域4中得到预览; 
  区域2:我们可以对已选中的某条映射关系进行删除、修改,也可以为某个activity新增intent-fillter; 
  区域3:我们可以在这里输入一个url,操作面板会告知我们这个url是用在哪个activity上; 
  3、为activity新增intenr-filter 
  点击区域2中的 + 打开新增面板 
  
  在这个面板中选中目标activity,配置host、path(可选)后点击Ok即可。 
  例如我有一个未配置意图过滤器的ThirdActivity,在清单文件中是这样的: 
   
  我们在新增面板中为该activity新增配置后,再看看清单文件是怎样的。 
   
  下图就是配置后的ThirdActivity意图 
  
  我们可以看到,和我们手写的intent-filter一毛一样! 
  4、为目标activity自动插入解析对应intent的代码 
  例如我的ThirdActivity空空如下: 
   
  现在,我们点击app链接助手面板中的Select Activity按钮,选中ThirdActivity点击Insert Code后怎么样: 
  
  以下就是插入代码后的ThirdActivity 
   
   
  5、生成链接数字证书文件Digital Asset Links(DAL) 
  点击打开链接助手的Open Digital Asset Links File Generator按钮,打开关联网站操作面板: 
  
  
  我们可以看到: 
  区域1:域名和包名已经自动填充好了 
  区域2:这里可以设置是否让网页和我们的APP共享用户的登陆信息,如果选择支持的话,需要键入网页的登陆地址,并且在我们的DAL证书中的relation项的值就变为:delegate_permission/common.get_login_creds。 
  我这里只是测试,就不支持共享登陆信息了。 
  区域3:这里可以选择我们的DAL证书是在debug环境用还是release环境用,如果选择生成的是release环境的证书,就还需要选择我们release打包用的keystore文件。 
  区域4:当我们点击Generate Digital Asset Links 按钮后,这里就可以预览我们生成的DAL文件详情了。我们可以看到,由于我在区域2中未勾选允许网页和App共享登陆信息,所以生成的DAL文件的relation的值为:delegate_permission/common.handle_all_urls。 
  然后点击Save file按钮,将我们的DAL文件下载下来,让后台人员把它上传到域名下的 .well-known目录下即可(注意:该目录以一个点开头,且Content-Type必须是application/json添加到http响应头)。例如我这里的域名是http://www.jack_bear_csdn.com,那DAL文件在服务器中的路径就是:http://www.jack_bear_csdn.com/.well-known/assetlinks.json。 
  区域5:完成了以上步骤,我们点击Link and Verify按钮,会产生以下结果: 
  5.1:项目res目录下的strings文件会生成一个名字为asset_statements的字符串: 
  
  5.2:产生的字符串会被添加到清单文件中的application节点下: 
  
  5.3:对应的activity的intent-filter里会加入一个是否自动认证的属性: 
   
  6、测试你的链接 
  完成了以上配置工作,我们回到链接助手面板,点击Test App Links按钮进入测试面板,键入对应的Url后点击Run Test按钮,可以模拟用户点击链接的操作: 
  

  到这里,我们可以知道:Android App Links之所以能够确保只有自己的App能打开对应的链接是因为DAL文件的作用。我们可以在6.0以上的手机中看到App都能被哪些链接打开,如下图: 
   
--------------------- 
补充app link :原文:https://blog.csdn.net/jack_bear_csdn/article/details/80579474 
 

猜你喜欢

转载自blog.csdn.net/MYBOYER/article/details/84979117