一、概述
当你的应用中WebView打开一个H5页面,在这个页面中需要可以打开第三方App页面,通用的跳转方式为Scheme协议和Intent协议。
Scheme格式
客户端自定义的 URL 作为从一个应用调用另一个的基础,遵循 RFC 1808 (Relative Uniform Resource Locators) 标准。这跟我们常见的网页内容 URL 格式一样。
一个普通的 URL 分为几个部分,scheme、host、relativePath、query。
比如:http://www.baidu.com/s?rsv_bp=1&rsv_spt=1&wd=NSurl&inputT=2709,这个URL中,scheme 为 http,host 为 www.baidu.com,relativePath 为 /s,query 为 rsv_bp=1&rsv_spt=1&wd=NSurl&inputT=2709。
一个应用中使用的 URL 例子(该 URL 会调起车辆详情页):uumobile://mobile/carDetail?car_id=123456,其中 scheme 为 uumobile,host 为 mobile,relativePath 为 /carDetail,query 为 car_id=123456。
Intent格式
intent:
HOST/URI-path // Optional host
Intent;
package=[string];
action=[string];
category=[string];
component=[string];
scheme=[string];
end;
举个栗子
```java
intent:
//scan/
#Intent;
package=com.sapp.android;
scheme=fengye;
end;
即:
intent://scan/#Intent;scheme= fengye;package=com.sapp.android;end
intent://platformapi/startapp?appId=20000013&pwdType=ordinaryPassword&_t=1456301771669#Intent;scheme=alipays;package=com.eg.android.AlipayGphone;end
二、在Webview支持Scheme和intent协议
在WebViewClient
的shouldOverrideUrlLoading
方法中实现以下代码:
@Override
public boolean shouldOverrideUrlLoading(WebView view, String newurl) {
try {
//处理intent协议
if (newurl.startsWith("intent://")) {
Intent intent;
try {
intent = Intent.parseUri(newurl, Intent.URI_INTENT_SCHEME);
intent.addCategory("android.intent.category.BROWSABLE");
intent.setComponent(null);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
intent.setSelector(null);
}
List<ResolveInfo> resolves = context.getPackageManager().queryIntentActivities(intent,0);
if(resolves.size()>0){
startActivityIfNeeded(intent, -1);
}
return true;
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
// 处理自定义scheme协议
if (!newurl.startsWith("http")) {
MyLogUtil.LogI("yxx","处理自定义scheme-->" + newurl);
try {
// 以下固定写法
final Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse(newurl));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
} catch (Exception e) {
// 防止没有安装的情况
e.printStackTrace();
ToastManager.showToast("您所打开的第三方App未安装!");
}
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return super.shouldOverrideUrlLoading(view, newurl);
}
三、App中支持第三方App或者浏览器跳转自己App
修改Manifest
文件,给想要接收跳转的Activity
添加<intent-filter>
配置,例如:
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!--需要添加下面的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="fengye"/>
</intent-filter>
</activity>
然后在MainActivity
的onCreate
方法中获取相关传递数据。例如:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@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();
Log.e(TAG, "scheme: "+uri.getScheme());
Log.e(TAG, "host: "+uri.getHost());
Log.e(TAG, "port: "+uri.getPort());
Log.e(TAG, "path: "+uri.getPath());
Log.e(TAG, "queryString: "+uri.getQuery());
Log.e(TAG, "queryParameter: "+uri.getQueryParameter("key"));
}
}