Android项目通过scheme在WebView中打开应用

  • 需求:在A应用的一个Activity中包含了WebView,WebView加载的是第三方的应用的数据,想要在该WebView页面打开第三方应用B,即在WebView通过点击事件或者链接打开第三方应用B。

1.scheme协议定义用途及需求的实现思路

1.Android中的scheme是一种页面内跳转协议,是一种非常好的实现机制;
2.通过定义自己的scheme协议,可以非常方便的跳转app中的各个页面;
3.在h5页面定义链接,跳转到指定的activity页面。客户端向h5页面注册一个urlscheme,然后由scheme协议用于从浏览器启动该activity;
4.使用场景归纳:客户端根据服务端下发的url跳转到指定的页面;从h5页面跳转到相应的activity页面;app根据url跳转到另一个指定的app页面(大型的公司,通过热门的链接跳转到另一个app);

2.scheme在android中的使用位置

<application
		        //省略无关代码...>
		<activity android:name=".MainActivity">
            <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="string"								
			              android:host="string"
			              android:port="string"
			              android:path="string"
			              android:pathPattern="string"
			              android:pathPrefix="string"
			              android:mimeType="string" />
            </intent-filter>
        </activity>
</application>

3.scheme 协议定义和 http 协议类似,都是标准的 URI 结构

[scheme:][//host:port][path][?query][#fragment]
scheme : 协议名称 - 必须
host : 协议地址 - 必须
port : 协议的端口,可以不填
path : 协议路径,可用 / 连接多个
query : 携带的参数可用 & 连接多个
fragment : 锚点

4.demo实例

  • 4.1.应用A的代码
//1.静态的h5页面代码,位置:/main/assets/test.html
<!DOCTYPE html>
<html lang="en">
<!-- window.location = params  或者 window.location.href = params  均可-->
<head>
    <script language="javascript">
    function startApp(params)
    {
        window.location.href = params
    }
    </script>
</head>
<body>
    <input type="button" onclick="startApp('definedscheme://main.definedhost')" value="启动app"/>
</body>

//2.activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    
    <WebView
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

//3.MainActivity类
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.webkit.WebView;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        WebView webView = findViewById(R.id.webview);
        webView.loadUrl("file:///android_asset/test.html");
        webView.getSettings().setJavaScriptEnabled(true);
        //这里有一个注意事项,不能调用setWebViewClient方法,调用后会出现跳转不成功的情况,
        //具体原因自己还没有弄清楚,有知道的小伙伴,望告知。
    }
}

4.2.应用B的代码

//1.AndroidManifest.xml
<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="app1"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <!-- TODO 需要添加下面的intent-filter配置,要新写一个intent-filter,如果直接写在launcher打开的filter中则会app图标消失-->
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <!-- TODO scheme 允许在浏览器中打开-->
                <category android:name="android.intent.category.BROWSABLE" />
                <!-- TODO scheme 相关信息配置-->
                <data android:scheme="definedscheme" android:host="main.definedhost">
                </data>
            </intent-filter>
        </activity>
</application>
    
//2.activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <TextView
        android:layout_width="wrap_content"
        android:id="@+id/text"
        android:text="这是被唤起的app页面"
        android:layout_height="wrap_content" />
</LinearLayout>

//3.MainActivity类
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    private String TAG = "TAG";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent = getIntent();
        Log.e(TAG, "scheme:"  + intent.getScheme());
        Uri uri = intent.getData();
        if (uri != null) {
            // 获取 scheme 名称
            Log.e(TAG, "scheme: " + uri.getScheme()); 
            // 获取 scheme 的host
            Log.e(TAG, "host: " + uri.getHost());     
            // 获取 scheme 的路径
            Log.e(TAG, "path: " + uri.getPath());     
            // 获取 scheme 的参数,?后面的部分
            Log.e(TAG, "queryString: " + uri.getQuery()); 
            // 获取 scheme 中的 param 参数
            Log.e(TAG, "queryParameter: " + uri.getQueryParameter("param")); 
        }
    }
}
  • 4.3.注意事项

步骤4.2,在AndroidManifest.xml文件中,MainActivity中要新写一个intent-filter,如果直接写在launcher打开的filter中则会app图标消失(因为category被覆盖为DEAFAULT)

  • 4.4.其中的 intent 实例有下面的方法可以获取相应的 scheme 信息:
getScheme() :获取Uri中的scheme名称:[scheme:]
getSchemeSpecificPart() :获取Uri中的scheme-specific-part:部分:[//host:port][path]
getFragment() :获取Uri中的Fragment部分:[#fragment]
getAuthority() :获取Uri中Authority部分:[//host:port]
getPath() :获取Uri中path部分:[path]
getQuery() :获取Uri中的query部分:[?query]
getHost() :获取Authority中的Host字符串
getPost() :获取Authority中的Port字符串
List< String> getPathSegments() :依次提取出Path的各个部分的字符串,以字符串数组的形式输出
getQueryParameter(String key) :获取query部分中 key 对应的参数值

5.总结

  • 在实际项目中加载的是具体的网页,若需要传递参数到第三方应用中,可以通过CookieManager对象写入需要传递的数据,然后在h5页面动态的传递参数,例如:将上面的静态页面中startApp(params)方法的形参params赋值为definedscheme://main.definedhost?canshu1=value1&canshu2=value2,则静态的h5页面变动的代码更改为:
<input type="button" onclick="startApp('definedscheme://main.definedhost?canshu1=value1&canshu2=value2')" value="启动app"/>
  • 此时,在被唤醒的app中可以获取键为canshu1和canshu2所应用的值value1和value2,即传递过来的值。
  • 最后总结:该文章介绍了在WebView中打开第三方应用的实现方式,且可以传递参数。如有不足之处,请大家多多指正!觉得有所帮助,请点个赞呗。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值