專案新需求:接收一個支付寶二維碼支付url,通過webview開啟對應的支付寶app支付頁面; 之前在網上找了段程式碼結果適配有問題,然後就順便研究下,記錄(liu)在(shui)此(zhang);
測試過的機型 : 紅米1s(4.4.4), 華為TAG-AL100(5.1), 華為KNT-AL20(6.0), exus6p(7.1.1);
接收到的支付連結 : url=https://qr.alipay.com/stx01744jxpniu1ijb5wr7d
P.S. 具體規則可以看 螞蟻金服文件
之前檢視到的文章大多類似 這篇;
主要程式碼:
//啟動支付寶,並跳轉到付款頁面
if (url.contains("platformapi/startapp")) {
startAlipayActivity(url);
}
private void startAlipayActivity(String url) {
LogUtils.d("alipay", "startUp");
Intent intent;
try {
intent = Intent.parseUri(url,
Intent.URI_INTENT_SCHEME);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setComponent(null);
startActivity(intent);
LogUtils.d("alipay", "start intent = " + intent.toString());
} catch (Exception e) {
e.printStackTrace();
LogUtils.d("alipay", "error " + e.getMessage());
}
}
複製程式碼
不過運氣不好,我手上的機子Nexus6P系統是7.1.1的,執行不成功,一直停留在網頁中,並未跳轉,直接使用斷點chrome://inspect功能,發現最終的url是被encode過的,難怪條件不匹配,後來嘗試了UrlDecode在判斷,依然不行,然後嘗試單獨判斷兩個關鍵字,也是呼叫不成功,鬱悶,在網上沒搜尋到現成的方法,就按照 上面文章 的思路,自己跟蹤一下url跳轉執行情況看看:
測試
功能程式碼
mWebSettings = mWebView.getSettings();
mWebSettings.setJavaScriptEnabled(true);
mWebSettings.setDomStorageEnabled(true);
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// 判斷方法1 ,註釋掉方法2再測試
if (url.contains("platformapi/startapp")) {
startAlipayActivity(url);
}else {
mWebView.loadUrl(url)
}
return true;
// 判斷方法2,註釋掉方法1再測試
if (url.contains("platformapi") && url.contains("startapp")) {
startAlipayActivity(url);
} else {
iew.loadUrl(url)
}
return true;
}
......
}
複製程式碼
分別測試方法1和方法2,看看兩種呼叫的情況,四臺機子測試結果:
- 原始 urlOri =
https://qr.alipay.com/stx01744jxpniu1ijb5wr7d
- 第一次載入返回: urlFirst =
https://mobilecodec.alipay.com/client_download.htm?qrcode=stx01744jxpniu1ijb5wr7d
- 第二次載入返回: urlHttps =
https://ds.alipay.com/?from=mobilecodec&scheme=alipays%3A%2F%2Fplatformapi%2Fstartapp%3FsaId%3D10000007%26clientVersion%3D3.7.0.0718%26qrcode%3Dhttps%253A%252F%252Fqr.alipay.com%252Fstx01744jxpniu1ijb5wr7d%253F_s%253Dweb-other
- 這個時候通過判斷
url.contains("platformapi/startapp"))
自然會由於url編碼的原因判斷失敗,再次呼叫mWebView.loadUrl(urlHttps)
: - 此時:
- 對於4.4/5.1/6.0機子的
WebView
來說:- 繼續載入 urlHttps 的話會返回一個intent : urlIntent =
intent://platformapi/startapp?saId=10000007&clientVersion=3.7.0.0718&qrcode=https%3A%2F%2Fqr.alipay.com%2Fstx01744jxpniu1ijb5wr7d%3F_s%3Dweb-other&_t=1483682394666#Intent;scheme=alipays;package=com.eg.android.AlipayGphone;end
- 通過解析它獲取到 targetIntent =
Intent { act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=https://ds.alipay.com/... }
- 成功調起支付寶App;
- 繼續載入 urlHttps 的話會返回一個intent : urlIntent =
- 而對於Nexus6p 7.1.1系統來說,返回的url還是那個 urlHttps, 無法滿足條件,也自然無法進行解析;
- 而如果通過分開判斷兩個關鍵字
(url.contains("platformapi") && url.contains("startapp"))
來解析intent的話,4.4/5.1機子的webview無法正常跳轉,而6.0/7.1.1的機子則正常;
適配方案
綜上, 在6.0及以上機子,可以直接對支付寶伺服器返回的https url進行解析並調起支付寶app跳轉到指定的支付頁面,而之前的機型則直接通過webview對https url進行載入,會返回一個inent url再進行跳轉:
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.contains("platformapi/startapp")) {
startAlipayActivity(url);
// android 6.0 兩種方式獲取intent都可以跳轉支付寶成功,7.1測試不成功
} else if ((Build.VERSION.SDK_INT > Build.VERSION_CODES.M)
&& (url.contains("platformapi") && url.contains("startapp"))) {
startAlipayActivity(url);
} else {
mWebView.loadUrl(url)
}
return true;
}
}
// 調起支付寶並跳轉到指定頁面
private void startAlipayActivity(String url) {
Intent intent;
try {
intent = Intent.parseUri(url,
Intent.URI_INTENT_SCHEME);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setComponent(null);
startActivity(intent);
finish();
} catch (Exception e) {
e.printStackTrace();
}
}
複製程式碼
擴充套件,網頁調起原生app
從瀏覽器或者Webview中喚醒APP 如何在瀏覽器中點選連結啟動App AS2.3直接提供了介面操作,很方便
官網這篇 Android Intents with Chrome 也解釋很清楚了,在 AndroidManifest.xml
中需要指定目標Activity的 category
屬性,新增 android.intent.category.BROWSABLE
,當然還要指定跳轉url的 host/scheme等值才行,比如:
<activity
android:name="YourActivity">
<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:host="platformapi.startapp.redeemcode"
android:scheme="uplusgo"/>
</intent-filter>
</activity>
複製程式碼
就可以在html頁面中設定a標籤指定其連結為 uplusgo://platformapi.startapp.redeemcode?your_parameter_name=...
,點選啟動應用,在Activity中通過如下方式來獲取附加引數:
Intent mIntent = getIntent();
Uri uri = mIntent.getData();
if (uri != null) {
String value = uri.getQueryParameter("your_parameter_name");
}
複製程式碼