c
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<queries>
<package android:name="com.tencent.mm"/>
<package android:name="com.eg.android.AlipayGphone"/>
</queries>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<application
android:name=".MyApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:networkSecurityConfig="@xml/network_security_config"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<meta-data
android:name="UMENG_CHANNEL"
android:value="${UMENG_CHANNEL_VALUE}" />
<activity
android:name=".SplashActivity"
android:label="智商测试趣测MBTI"
android:exported="true"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity" />
<activity android:name=".splash.PrivacyWebActivity"/>
</application>
</manifest>
添加的是
c
<queries>
<package android:name="com.tencent.mm"/>
<package android:name="com.eg.android.AlipayGphone"/>
</queries>
webview如下
c
package com.zs.test.fragment;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.JavascriptInterface;
import android.webkit.ValueCallback;
//import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
//import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.just.agentweb.AgentWeb;
import com.just.agentweb.WebChromeClient;
import com.just.agentweb.WebViewClient;
import com.zs.test.R;
import com.zs.test.util.DeviceUtil;
import com.zs.test.util.PackageUtil;
import com.zs.test.util.SharedPreferencesUtils;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
public class WebViewFragment2 extends Fragment {
private WebView myWebView;
private TextView statusBarText;
private ImageButton btnBack;
private String channel;
private String packageName;
private String osVersion;
private String osType = "Android";
private String brand;
private String model;
private String appVersion;
private String appName = "cstest";
private String deviceToken;
private String deviceId;
private String url;
public static WebViewFragment2 newInstance(String url, String title, boolean showBack) {
WebViewFragment2 fragment = new WebViewFragment2();
Bundle args = new Bundle();
args.putString("url", url);
args.putString("title", title);
args.putBoolean("showBack", showBack);
fragment.setArguments(args);
return fragment;
}
private WebChromeClient mWebChromeClient = new WebChromeClient() {
/*override fun onProgressChanged(view: WebView?, newProgress: Int) {
}*/
};
private WebViewClient mWebViewClient = new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
@Nullable
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
return super.shouldInterceptRequest(view, request);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
Uri uri = request.getUrl();
String scheme = uri.getScheme();
// 检查自定义协议
if (!scheme.equals("http") && !scheme.equals("https")) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
if (intent.resolveActivity(getContext().getPackageManager()) != null) {
startActivity(intent);
} else {
Log.e("WebViewFragment", "无法处理的自定义协议: " + scheme);
}
} catch (Exception e) {
Log.e("WebViewFragment", "处理自定义协议时发生错误: " + e.getMessage());
}
return true; // 拦截自定义协议,不交给 WebView 处理
}
return false; // 对于普通 HTTP 或 HTTPS 链接,让 WebView 自行加载
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// 对于旧版 Android (API < 21),应该使用这个重载方法
Uri uri = Uri.parse(url);
String scheme = uri.getScheme();
// 如果是 HTTP 或 HTTPS 协议,WebView 继续加载
if (scheme.equals("http") || scheme.equals("https")) {
return false;
}
// 处理自定义协议(如 weixin://)
try {
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 通过 Intent 打开相应的 App(微信等)
if (intent.resolveActivity(getContext().getPackageManager()) != null) {
startActivity(intent);
} else {
Log.e("WebView", "无法处理的自定义协议: " + scheme);
}
} catch (Exception e) {
e.printStackTrace();
Log.e("WebView", "处理自定义协议时发生错误: " + e.getMessage());
}
return true; // 拦截这个 URL,不让 WebView 继续加载
}
/*override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
//showLoadingDialog()
}
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
//hideLoadingDialog()
if(view==null) return
if(view==null) return
if(mTitle.isBlank() && !url.isNullOrBlank()){
mHbvTitle.setTitle(view!!.title?:"")
}
}
override fun shouldInterceptRequest(
view: WebView?,
request: WebResourceRequest?
): WebResourceResponse? {
if(request!=null){
}
return super.shouldInterceptRequest(view, request)
}
override fun shouldOverrideUrlLoading(
view: WebView?,
request: WebResourceRequest?
): Boolean {
return super.shouldOverrideUrlLoading(view, request)
}*/
};
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_webview, container, false);
statusBarText = rootView.findViewById(R.id.statusBarText);
btnBack = rootView.findViewById(R.id.btnBack);
//myWebView = rootView.findViewById(R.id.webview);
FrameLayout fl = (FrameLayout) rootView.findViewById(R.id.fl);
AgentWeb mAgentWeb = AgentWeb.with(this)
.setAgentWebParent(fl, new LinearLayout.LayoutParams(-1, -1))
.closeIndicator()
.setWebChromeClient(mWebChromeClient)
.setWebViewClient(mWebViewClient)
.createAgentWeb()
.ready()
.go(url);
myWebView = mAgentWeb.getWebCreator().getWebView();
WebSettings setting = myWebView.getSettings();
setting.setJavaScriptEnabled(true);
setting.setJavaScriptCanOpenWindowsAutomatically(true);
if (getArguments() != null) {
url = getArguments().getString("url");
Log.d("urlds",url);
String title = getArguments().getString("title");
statusBarText.setText(title);
boolean showBack = getArguments().getBoolean("showBack");
if (showBack) {
getActivity().runOnUiThread(() -> btnBack.setVisibility(View.VISIBLE));
}
}
// 设置返回按钮的点击事件
btnBack.setOnClickListener(v -> {
if (myWebView.canGoBack()) {
myWebView.goBack(); // 如果 WebView 可以返回,执行 WebView 的返回操作
} else {
getActivity().onBackPressed(); // 否则执行默认的返回操作
}
});
// 设置沉浸式状态栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getActivity().getWindow().setStatusBarColor(Color.TRANSPARENT);
getActivity().getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
// 初始化SharedPreferencesUtils,用于获取设备Token
SharedPreferencesUtils prefs = SharedPreferencesUtils.getInstance(getContext());
deviceToken = prefs.getString(SharedPreferencesUtils.DEVICE_TOKEN, "");
// 获取应用相关信息
packageName = getActivity().getPackageName();
osVersion = Build.VERSION.RELEASE;
brand = Build.BRAND;
model = Build.MODEL;
appVersion = DeviceUtil.getAppVersion(getContext());
deviceId = DeviceUtil.getDeviceUniqueId(getContext());
// 获取渠道信息
channel = PackageUtil.getUmengChannelName(getContext());
// 启用 JavaScript
myWebView.getSettings().setJavaScriptEnabled(true);
// 设置支持弹出新窗口
myWebView.getSettings().setSupportMultipleWindows(true);
// 加载拼接后的URL
myWebView.loadUrl(url);
// 设置 WebViewClient,处理页面加载过程中的事件
// myWebView.setWebViewClient(new WebViewClient() {
// @Override
// public void onPageStarted(WebView view, String url, android.graphics.Bitmap favicon) {
// super.onPageStarted(view, url, favicon);
// }
//
// @Override
// public void onPageFinished(WebView view, String url) {
// super.onPageFinished(view, url);
// }
//
// @Override
// public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
// return super.shouldOverrideUrlLoading(view, request);
// }
// });
// 设置 WebChromeClient,处理进度条等操作
myWebView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
}
});
// 请求头设置
Map<String, String> headers = new HashMap<>();
// headers.put("channel", channel);
// headers.put("packagename", packageName);
// headers.put("device-system", osVersion);
// headers.put("device-platform", osType);
// headers.put("device-brand", brand);
// headers.put("device-model", model);
// headers.put("host-version", appVersion);
// headers.put("host-app-name", appName);
// headers.put("device-id", deviceId);
// headers.put("device-Token", deviceToken);
// // 拼接URL并打印
// StringBuilder urlWithParams = new StringBuilder(url);
// urlWithParams.append("?deviceSystem=").append(osVersion)
// .append("&devicePlatform=").append(osType)
// .append("&deviceBrand=").append(brand)
// .append("&deviceModel=").append(model)
// .append("&version=").append(appVersion)
// .append("&loginInfoRet=").append("arg");
// Log.d("FinalUrl", "Final URL: " + urlWithParams.toString());
myWebView.addJavascriptInterface(new Object() {
@JavascriptInterface
public void showHeaderBarBackIcon(boolean show) {
if (show) {
getActivity().runOnUiThread(() -> btnBack.setVisibility(View.VISIBLE));
} else {
getActivity().runOnUiThread(() -> btnBack.setVisibility(View.GONE));
}
}
@JavascriptInterface
public void setHeaderBarBackGroundColor(String color) {
Log.d("js回调", "状态栏颜色" + color);
getActivity().runOnUiThread(() -> getView().findViewById(R.id.statusBar).setBackgroundColor(Color.parseColor(color)));
}
@JavascriptInterface
public void setHeaderBarStyle(boolean isBlack) {
Log.d("js回调", "字体颜色" + isBlack);
getActivity().runOnUiThread(() -> {
if (isBlack) {
statusBarText.setTextColor(Color.BLACK);
btnBack.setImageResource(R.drawable.ic_back_black);
} else {
statusBarText.setTextColor(Color.WHITE);
btnBack.setImageResource(R.drawable.ic_back_white);
}
});
}
@JavascriptInterface
public void getLoginInfo() {
Log.d("js回调", "开始调登陆");
loginInfoRet(channel);
}
@JavascriptInterface
public void openLink(String uriStr) {
try {
Uri uri = Uri.parse(uriStr);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
private void loginInfoRet(String channel) {
runOnMainThread(() -> {
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("packageName", packageName);
jsonObject.put("channel", channel);
jsonObject.put("version", appVersion);
jsonObject.put("token", deviceToken);
jsonObject.put("devicePlatform", "android");
jsonObject.put("deviceSystem", Build.VERSION.RELEASE);
jsonObject.put("deviceBrand", Build.BRAND);
jsonObject.put("deviceModel", Build.MODEL);
jsonObject.put("deviceId", deviceId);
String str = jsonObject.toString();
String jsCode = "javascript:loginInfoRet(" + str + ");";
Log.d("JS Code", "Executing: " + jsCode);
if (myWebView != null) {
myWebView.evaluateJavascript("javascript:loginInfoRet" + str + ");", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
Log.d("JS Result", "Result from JS: " + value);
}
});
}
} catch (JSONException e) {
e.printStackTrace();
}
});
}
}, "Android");
return rootView;
}
@Override
public void onDetach() {
super.onDetach();
if (myWebView != null) {
myWebView.destroy();
}
}
public void runOnMainThread(Runnable block) {
new Handler(Looper.getMainLooper()).post(block);
}
}
MainActivity
c
package com.zs.test;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;
import com.zs.test.common.Global;
import com.zs.test.fragment.WebViewFragment;
import com.zs.test.fragment.WebViewFragment2;
import com.zs.test.util.SharedPreferencesUtils;
public class MainActivity extends AppCompatActivity {
private boolean isBackPressedOnce = false; // 标志用户是否已经按过一次返回键
private final Handler handler = new Handler(Looper.getMainLooper()); // 用于延时清除标志
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferencesUtils preferencesUtils = SharedPreferencesUtils.getInstance(this);
String mainWebUrl = preferencesUtils.getString(SharedPreferencesUtils.MAIN_WEB_URL,"");
// 启动 WebViewFragment
if (savedInstanceState == null) {
WebViewFragment2 webViewFragment = WebViewFragment2.newInstance(mainWebUrl, "智商测试",false);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, webViewFragment);
transaction.commit();
}
}
@Override
public void onBackPressed() {
if (isBackPressedOnce) {
// 第二次按返回键,退出应用
super.onBackPressed();
finishAffinity(); // 结束所有活动,退出应用
System.exit(0); // 彻底退出进程
} else {
// 第一次按返回键,提示用户
isBackPressedOnce = true;
Toast.makeText(this, "再按一次返回键退出程序", Toast.LENGTH_SHORT).show();
// 延时2秒后重置标志
handler.postDelayed(() -> isBackPressedOnce = false, 2000);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// 清除所有回调,避免内存泄漏
handler.removeCallbacksAndMessages(null);
}
}