脚本
我的Android应用程序中有一个WebView,其中包含一个嵌入Soundcloud(来自Embedly).这个嵌入有两个按钮:“在Soundcloud上播放”和“在浏览器中收听”.
“Play on Soundcloud”按钮包含格式为intent的URL:// tracks:257659076#Intent; scheme = soundcloud; package = com.soundcloud.android; end
码
我的WebView使用自定义WebViewClient(因为我需要拦截一些不同内容的URL).
protected class WebViewClient extends android.webkit.WebViewClient {
public WebViewClient() { }
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
PackageManager packageManager = context.getPackageManager();
// Create an Intent from the URL.
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
// Find out if I have any activities which will handle the URL.
List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(intent, 0);
// If we have an app installed that can handle the URL, then use it.
if (resolveInfoList != null && resolveInfoList.size() > 0) {
Intent viewUrlIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
context.startActivity(viewUrlIntent);
}
else {
// Do something else.
}
return true;
}
}
问题
单击“在浏览器中监听”可以在嵌入本身中播放轨道并且工作正常.单击“在Soundcloud上播放”将调用上面的WebViewClient中的shouldOverrideUrlLoading(如预期的那样).但是,我找到活动的代码找不到任何可以处理此Soundcloud URL的代码.
如果我没有在WebView上设置我的WebViewClient(所以它只做自己的事情),“Play on Soundcloud”按钮将按预期工作并启动Soundcloud应用程序.
临时(废话)解决方案
我已经设法通过解析URL获取轨道ID,然后使用Soundcloud明确接受的格式构建新URL(感谢this SO帖子)来实现我想要它做的事情. Soundcloud应用程序将接受格式为“soundcloud:// tracks:[TRACK_ID]”的URL.
但为什么?
要么我整个“找出哪些活动可以处理这个URL”的事情是错误的,或者可能(?!)WebView使用的默认WebViewClient明确处理这个?!似乎难以置信.
最佳答案 我只是在这里扩展Temporary(废话)解决方案,所以这远非一个完美的答案,但可能仍然可以帮助那些绝对需要让这个工作的人,也有私人轨道.
如果轨道是公共的,则替换方法有效,但是私有轨道不起作用,可能是因为意图URL中缺少秘密令牌.
不幸的是,嵌入播放器不包含我需要生成的URL的所有必要部分,除了iframe内部,由于跨源策略我无法访问.所以除了iframe代码我还需要共享链接.
我最终做的是确保包含HTML页面的共享链接作为JS变量.然后,我使用Java读取该变量,并使用该URL创建一个新的Intent.这是有效的,因为官方应用程序还会注册所有soundcloud.com网址.
因此,对于私人曲目,这将转到HTML页面:
<script>var soundCloudURL = "https://soundcloud.com/my-profile/my-track/my-secret-token";</script>
然后在你的Android应用程序中你会有这样的事情:
@Override
public boolean shouldOverrideUrlLoading (WebView view, String url) {
if (uri.getScheme().contains("intent")) {
openSoundCloudPlayer();
return true;
}
}
private void openSoundCloudPlayer() {
appWebView.evaluateJavascript("(function() { return soundCloudUrl })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String soundCloudUrl) {
// JS null is converted into a string "null", not Java null.
if (soundCloudUrl != "null") {
// Take out the quotes from the string
soundCloudUrl = soundCloudUrl.replace("\"", "");
Uri newUri = Uri.parse(soundCloudUrl);
Intent intent = new Intent(Intent.ACTION_VIEW, newUri);
startActivity(intent);
}
}
});
}