前言
简单记录下一下Android 应用内部打开网页的几种方式,方便自己查阅。
内容来自AI助手
正文
方式1
使用内置浏览器。
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.biumall.com")); startActivity(browserIntent);
如果设备至少需要一个浏览器,否则就会崩溃,主要看AndroidRuntime日志。下面是没有浏览器时的打印。
AndroidRuntime: FATAL EXCEPTION: main AndroidRuntime: Process: com.biumall.browser, PID: 6782 AndroidRuntime: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=https://www.biumall.com/... } AndroidRuntime: at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:2007) AndroidRuntime: at android.app.Instrumentation.execStartActivity(Instrumentation.java:1673) AndroidRuntime: at android.app.Activity.startActivityForResult(Activity.java:4586) AndroidRuntime: at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:780) AndroidRuntime: at android.app.Activity.startActivityForResult(Activity.java:4544) AndroidRuntime: at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:761) AndroidRuntime: at android.app.Activity.startActivity(Activity.java:4905) AndroidRuntime: at android.app.Activity.startActivity(Activity.java:4873) AndroidRuntime: at com.biumall.browser.MainActivity.useBrowser(MainActivity.java:115) AndroidRuntime: at com.biumall.browser.MainActivity.access$300(MainActivity.java:24) AndroidRuntime: at com.biumall.browser.MainActivity$1.handleMessage(MainActivity.java:43) AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:106) AndroidRuntime: at android.os.Looper.loop(Looper.java:193) AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6691) AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:982) ActivityManager: Force finishing activity com.biumall.browser/.MainActivity
方式2
使用WebView
<WebView android:id="@+id/main_wb_web_view" android:layout_width="match_parent" android:layout_height="match_parent" />
WebView webView = findViewById(R.id.main_wb_web_view); webView.getSettings().setJavaScriptEnabled(true); webView.loadUrl("https://www.biumall.com");
Android 8.0开始,系统应用使用这个会崩溃,系统应用不让使用。
AndroidRuntime: Caused by: java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes AndroidRuntime: at android.webkit.WebViewFactory.getProvider(WebViewFactory.java:235) AndroidRuntime: at android.webkit.WebView.getFactory(WebView.java:2681) AndroidRuntime: at android.webkit.WebView.ensureProviderCreated(WebView.java:2676) AndroidRuntime: at android.webkit.WebView.setOverScrollMode(WebView.java:2741) AndroidRuntime: at android.view.View.<init>(View.java:4807) AndroidRuntime: at android.view.View.<init>(View.java:4948) AndroidRuntime: at android.view.ViewGroup.<init>(ViewGroup.java:661) AndroidRuntime: at android.widget.AbsoluteLayout.<init>(AbsoluteLayout.java:55) AndroidRuntime: at android.webkit.WebView.<init>(WebView.java:659) AndroidRuntime: at android.webkit.WebView.<init>(WebView.java:604) AndroidRuntime: at android.webkit.WebView.<init>(WebView.java:587) AndroidRuntime: at android.webkit.WebView.<init>(WebView.java:574)
AndroidManifest.xml中去掉
android:sharedUserId="android.uid.system"
如果不行去掉,就按照下面的方式进行hook。
根据参考文章整理的。当然如果有源码,也可以改源码(这后续有空写一下)。
@SuppressLint({"PrivateApi", "SoonBlockedPrivateApi", "DiscouragedPrivateApi"}) public void hookWebView() { int sdkInt = Build.VERSION.SDK_INT; try { Class<?> factoryClass = Class.forName("android.webkit.WebViewFactory"); Field field = factoryClass.getDeclaredField("sProviderInstance"); field.setAccessible(true); Object sProviderInstance = field.get(null); if (sProviderInstance != null) { Log.i(TAG, "sProviderInstance isn't null"); return; } Method getProviderClassMethod; if (sdkInt > 22) { getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass"); } else if (sdkInt == 22) { getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass"); } else { Log.i(TAG, "Don't need to Hook WebView"); return; } getProviderClassMethod.setAccessible(true); Class<?> factoryProviderClass = (Class<?>) getProviderClassMethod.invoke(factoryClass); Class<?> delegateClass = Class.forName("android.webkit.WebViewDelegate"); Constructor<?> delegateConstructor = delegateClass.getDeclaredConstructor(); delegateConstructor.setAccessible(true); if (null != factoryProviderClass) { if (sdkInt < 26) {//低于Android O版本 Constructor<?> providerConstructor = factoryProviderClass.getConstructor(delegateClass); providerConstructor.setAccessible(true); sProviderInstance = providerConstructor.newInstance(delegateConstructor.newInstance()); } else { Field chromiumMethodName = factoryClass.getDeclaredField("CHROMIUM_WEBVIEW_FACTORY_METHOD"); chromiumMethodName.setAccessible(true); String chromiumMethodNameStr = (String) chromiumMethodName.get(null); if (chromiumMethodNameStr == null) { chromiumMethodNameStr = "create"; } Method staticFactory = factoryProviderClass.getMethod(chromiumMethodNameStr, delegateClass); sProviderInstance = staticFactory.invoke(null, delegateConstructor.newInstance()); } } if (sProviderInstance != null) { field.set("sProviderInstance", sProviderInstance); Log.i(TAG, "Hook success!"); } else { Log.i(TAG, "Hook failed!"); } } catch (Throwable e) { Log.w(TAG, e); } }
在onCreate()中setContentView()之前调用即可
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // hookWebView(); setContentView(R.layout.activity_main); Log.d(TAG, "onCreate: "); }
这样私有应用中使用WebView就没啥问题了。
方式3
使用CustomTabsIntent,这个需要引入jar
implementation 'androidx.browser:browser:1.3.0'
使用方式就行
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); CustomTabsIntent customTabsIntent = builder.build(); customTabsIntent.launchUrl(this, Uri.parse("https://www.biumall.com"));
这个也是需要设备中至少有一个浏览器,要不然也会崩溃。
下面没有浏览器时崩溃日志打印;
AndroidRuntime: FATAL EXCEPTION: main AndroidRuntime: Process: com.biumall.browser, PID: 13466 AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.biumall.browser/com.biumall.browser.MainActivity}: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=https://www.biumall.com/... (has extras) } AndroidRuntime: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2925) AndroidRuntime: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3060) AndroidRuntime: at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) AndroidRuntime: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) AndroidRuntime: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1820) AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:106) AndroidRuntime: at android.os.Looper.loop(Looper.java:193) AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6691) AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:982) AndroidRuntime: Caused by: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=https://www.biumall.com/... (has extras) } AndroidRuntime: at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:2007) AndroidRuntime: at android.app.Instrumentation.execStartActivity(Instrumentation.java:1673) AndroidRuntime: at android.app.Activity.startActivityForResult(Activity.java:4586) AndroidRuntime: at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:780) AndroidRuntime: at android.app.Activity.startActivityForResult(Activity.java:4544) AndroidRuntime: at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:761) AndroidRuntime: at android.app.Activity.startActivity(Activity.java:4905) AndroidRuntime: at androidx.core.content.ContextCompat$Api16Impl.startActivity(ContextCompat.java:978) AndroidRuntime: at androidx.core.content.ContextCompat.startActivity(ContextCompat.java:318) AndroidRuntime: at androidx.browser.customtabs.CustomTabsIntent.launchUrl(CustomTabsIntent.java:483) AndroidRuntime: at com.biumall.browser.MainActivity.useCustomTabsIntent(MainActivity.java:108) AndroidRuntime: at com.biumall.browser.MainActivity.onCreate(MainActivity.java:60) AndroidRuntime: at android.app.Activity.performCreate(Activity.java:7136) AndroidRuntime: at android.app.Activity.performCreate(Activity.java:7127) AndroidRuntime: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271) AndroidRuntime: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2905) AndroidRuntime: ... 11 more ActivityManager: Force finishing activity com.biumall.browser/.MainActivity
小结
从上面看
使用WebView最简单,也不需要依赖设备中的浏览器。
CustomTabsIntent或startActivity都需要使用设备中的浏览器。
参考文章
通过百度AI和腾讯元宝查询并整理的。
《
© 版权声明