当前位置:   article > 正文

Android集成腾讯x5内核_android 腾讯x5浏览器内核

android 腾讯x5浏览器内核

腾讯x5内核 可替换android自带的webview,优化打开速度,相比之下 腾讯内核比跟原声的比真的6到飞起   

最近有在一个新项目中使用的x5内核,然后再初始化的时候 

onViewInitFinished中返回的一直是false 调用的还是系统的内核 建议这边先跑一下dome  用dome的代码 来进行注册  

然后

onDownloadFinish中一直返回-122  或者-134   建议在集成玩x5 后 访问
debugtbs.qq.com 查看问题所在 ,最后我删除app加重启手机 然后就下载成功了

腾讯X5内核官方sdk地址

首先导入项目的jar和os文件 

导入文件后 引入jar后 在 Application 初始化腾讯内核服务

  1. QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() {
  2. @Override
  3. public void onViewInitFinished(boolean arg0) {
  4. // TODO Auto-generated method stub
  5. //x5內核初始化完成的回调,为true表示x5内核加载成功,否则表示x5内核加载失败,会自动切换到系统内核。
  6. Log.d("app", " onViewInitFinished is " + arg0);
  7. }
  8. @Override
  9. public void onCoreInitFinished() {
  10. // TODO Auto-generated method stub
  11. }
  12. };
  13. //x5内核初始化接口
  14. QbSdk.initX5Environment(getApplicationContext(), cb);
还需要一个x5的工具类 来替换webview的工具   直接复制到项目中 备用
  1. public class X5WebView extends WebView {
  2. TextView title;
  3. private Context context;
  4. private WebViewClient client = new WebViewClient() {
  5. /**
  6. * 防止加载网页时调起系统浏览器
  7. */
  8. public boolean shouldOverrideUrlLoading(WebView view, String url) {
  9. if (url.startsWith("http:") || url.startsWith("https:")){
  10. view.loadUrl(url);
  11. Map<String, String> extraHeaders = new HashMap<String, String>();
  12. extraHeaders.put("Referer", "");//这里可换成自己域名 不写也没事
  13. view.loadUrl(url, extraHeaders);
  14. return false;
  15. }else {
  16. if (url.startsWith("weixin://wap/pay?")) {//这里拦截了支付 不跳转支付页面直接打开支付功能
  17. Intent intent = new Intent();
  18. intent.setAction(Intent.ACTION_VIEW);
  19. intent.setData(Uri.parse(url));
  20. context.startActivity(intent);
  21. }
  22. return true;
  23. }
  24. }
  25. };
  26. @SuppressLint("SetJavaScriptEnabled")
  27. public X5WebView(Context arg0, AttributeSet arg1) {
  28. super(arg0, arg1);
  29. this.context=arg0;
  30. this.setWebViewClient(client);
  31. // this.setWebChromeClient(chromeClient);
  32. // WebStorage webStorage = WebStorage.getInstance();
  33. initWebViewSettings();
  34. this.getView().setClickable(true);
  35. }
  36. //这是一些设置文件 具体的意思 可以百度 或者翻看我之前的博客 这里设置可以打开图片 视频还有自适应的主要功能
  37. private void initWebViewSettings() {
  38. WebSettings webSetting = this.getSettings();
  39. webSetting.setJavaScriptEnabled(true);
  40. webSetting.setJavaScriptCanOpenWindowsAutomatically(true);
  41. webSetting.setAllowFileAccess(true);
  42. webSetting.setLayoutAlgorithm(LayoutAlgorithm.NARROW_COLUMNS);
  43. webSetting.setSupportZoom(true);
  44. webSetting.setBuiltInZoomControls(true);
  45. webSetting.setUseWideViewPort(true);
  46. webSetting.setSupportMultipleWindows(true);
  47. // webSetting.setLoadWithOverviewMode(true);
  48. webSetting.setAppCacheEnabled(true);
  49. // webSetting.setDatabaseEnabled(true);
  50. webSetting.setDomStorageEnabled(true);
  51. webSetting.setGeolocationEnabled(true);
  52. webSetting.setAppCacheMaxSize(Long.MAX_VALUE);
  53. // webSetting.setPageCacheCapacity(IX5WebSettings.DEFAULT_CACHE_CAPACITY);
  54. webSetting.setPluginState(WebSettings.PluginState.ON_DEMAND);
  55. // webSetting.setRenderPriority(WebSettings.RenderPriority.HIGH);
  56. webSetting.setCacheMode(WebSettings.LOAD_NO_CACHE);
  57. // this.getSettingsExtension().setPageCacheCapacity(IX5WebSettings.DEFAULT_CACHE_CAPACITY);//extension
  58. // settings 的设计
  59. }
  60. @Override
  61. protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
  62. boolean ret = super.drawChild(canvas, child, drawingTime);
  63. return ret;
  64. }
  65. public X5WebView(Context arg0) {
  66. super(arg0);
  67. setBackgroundColor(85621);
  68. }
  69. }
现在准备工作就完成了  接下来创建一个新的activity文件 

先创建xml  主要就是一个framelayout 其他的导航栏什么的 根据自己的写 一般导航栏的名字 可根据网页的title修改 在java里面会给到代码 

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:app="http://schemas.android.com/apk/res-auto"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. android:orientation="vertical">
  7. <RelativeLayout
  8. android:layout_width="match_parent"
  9. android:layout_height="match_parent"
  10. android:layout_weight="1"
  11. android:orientation="vertical">
  12. <FrameLayout
  13. android:id="@+id/webView1"
  14. android:layout_width="match_parent"
  15. android:layout_height="match_parent"></FrameLayout>
  16. </RelativeLayout>
  17. </LinearLayout>

java文件代码  代码主要来源于官方dome 这里增加了 打开本地相册 还有一些提示框的相关功能

  1. public class BrowserActivity extends BaseActivity {
  2. /**
  3. * 作为一个浏览器的示例展示出来,采用android+web的模式
  4. */
  5. private X5WebView mWebView;
  6. private ViewGroup mViewParent;
  7. private ImageButton mBack;
  8. private ImageButton mForward;
  9. private ImageButton mExit;
  10. private ImageButton mHome;
  11. private ImageButton mMore;
  12. private Button mGo;
  13. private EditText mUrl;
  14. private static final String mHomeUrl = "url";
  15. private static final String TAG = "SdkDemo";
  16. private static final int MAX_LENGTH = 14;
  17. private boolean mNeedTestPage = false;
  18. private final int disable = 120;
  19. private final int enable = 255;
  20. private ProgressBar mPageLoadingProgressBar = null;
  21. public final static int FILE_CHOOSER_RESULT_CODE_FOR_ANDROID_5 = 2;
  22. private final static int FILE_CHOOSER_RESULT_CODE = 1;// 表单的结果回调
  23. public ValueCallback<Uri[]> mUploadMessageForAndroid5;
  24. private ValueCallback<Uri> uploadFile;
  25. TitleBar mTitleBar;
  26. public URL mIntentUrl;
  27. public static final String URLS = "url";
  28. public static final String TITLE = "title";
  29. private String weiuri;
  30. private Intent intent;
  31. KeyMapDailog dialogs;
  32. private String stringExtra;
  33. @Override
  34. protected int getLayoutID() {//设置xml路径
  35. return R.layout.activity_main;
  36. }
  37. public static Intent newIntent(Activity fromActivity, String url, String title) {
  38. Intent intent = new Intent(fromActivity, BrowserActivity.class);
  39. intent.putExtra(mHomeUrl, url);
  40. intent.putExtra(TITLE, title);
  41. return intent;
  42. }
  43. String[] mPermissionList = new String[]{Manifest.permission.CAMERA,
  44. Manifest.permission.READ_EXTERNAL_STORAGE};
  45. @Override
  46. protected void onCreate(Bundle savedInstanceState) {
  47. super.onCreate(savedInstanceState);
  48. getWindow().setFormat(PixelFormat.TRANSLUCENT);
  49. stringExtra = getIntent().getStringExtra(mHomeUrl);
  50. if (null == stringExtra) {
  51. return;
  52. }
  53. weiuri = new String(Urls.BASE_URL + "article/view?arcId=" + stringExtra);
  54. Intent intent = getIntent();
  55. if (weiuri.length() == 0) {
  56. return;
  57. }
  58. if (intent != null) {
  59. try {
  60. mIntentUrl = new URL(intent.getData().toString());
  61. } catch (MalformedURLException e) {
  62. e.printStackTrace();
  63. } catch (NullPointerException e) {
  64. } catch (Exception e) {
  65. }
  66. }
  67. //
  68. try {
  69. if (Integer.parseInt(android.os.Build.VERSION.SDK) >= 11) {
  70. getWindow()
  71. .setFlags(//硬件加速
  72. android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
  73. android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
  74. }
  75. } catch (Exception e) {
  76. }
  77. /*
  78. * getWindow().addFlags(
  79. * android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN);
  80. */
  81. //setContentView(R.layout.activity_mains);
  82. mViewParent = (ViewGroup) findViewById(R.id.webView1);
  83. initBtnListenser();
  84. mTestHandler.sendEmptyMessageDelayed(MSG_INIT_UI, 10);
  85. }
  86. private void changGoForwardButton(WebView view) {
  87. if (view.canGoBack())
  88. mBack.setAlpha(enable);
  89. else
  90. mBack.setAlpha(disable);
  91. if (view.canGoForward())
  92. mForward.setAlpha(enable);
  93. else
  94. mForward.setAlpha(disable);
  95. if (view.getUrl() != null && view.getUrl().equalsIgnoreCase(weiuri)) {
  96. mHome.setAlpha(disable);
  97. mHome.setEnabled(false);
  98. } else {
  99. mHome.setAlpha(enable);
  100. mHome.setEnabled(true);
  101. }
  102. }
  103. private void initProgressBar() {
  104. mPageLoadingProgressBar = (ProgressBar) findViewById(R.id.progressBar1);// new
  105. mPageLoadingProgressBar.setMax(100);
  106. mPageLoadingProgressBar.setProgressDrawable(this.getResources()
  107. .getDrawable(R.drawable.color_progressbar));
  108. }
  109. public View init() {
  110. mWebView = new X5WebView(this, null);
  111. mViewParent.addView(mWebView, new FrameLayout.LayoutParams(
  112. FrameLayout.LayoutParams.FILL_PARENT,
  113. FrameLayout.LayoutParams.FILL_PARENT));
  114. initProgressBar();
  115. mWebView.setWebViewClient(new WebViewClient() {
  116. @Override
  117. public boolean shouldOverrideUrlLoading(WebView view, String url) {
  118. //这里可拦截web的连接 进行相关操作
  119. //给个简单的例子
  120. if (url.startsWith("http:") || url.startsWith("https:")) {
  121. view.loadUrl(url);
  122. Map<String, String> extraHeaders = new HashMap<String, String>();
  123. extraHeaders.put("Referer", "");
  124. view.loadUrl(url, extraHeaders);
  125. return false;
  126. } else {
  127. if (url.contains("jxz://h5share")) { //这里拦截了url包换jxz://h5share 这段代码 然后从连接里面 找到sharedesc 等的一些参数 可以做相关操作
  128. Uri uri = Uri.parse(url);
  129. String sharedesc = uri.getQueryParameter("sharedesc");
  130. }//
  131. }
  132. return true;
  133. }
  134. @Override
  135. public void onPageFinished(WebView view, String url) {
  136. super.onPageFinished(view, url);
  137. if (view.getTitle().length() != 0) {
  138. mTitleBar.setTitle(view.getTitle());
  139. }
  140. mTestHandler.sendEmptyMessageDelayed(MSG_OPEN_TEST_URL, 5000);// 5s?
  141. if (Integer.parseInt(android.os.Build.VERSION.SDK) >= 16)
  142. changGoForwardButton(view);
  143. }
  144. });
  145. mWebView.setWebChromeClient(new WebChromeClient() {
  146. @Override
  147. public boolean onJsConfirm(WebView arg0, String arg1, String arg2,
  148. JsResult arg3) {
  149. return super.onJsConfirm(arg0, arg1, arg2, arg3);
  150. }
  151. View myVideoView;
  152. View myNormalView;
  153. CustomViewCallback callback;
  154. // /
  155. //
  156. /**
  157. * 全屏播放配置
  158. */
  159. @Override
  160. public void onShowCustomView(View view,
  161. CustomViewCallback customViewCallback) {
  162. FrameLayout normalView = (FrameLayout) findViewById(R.id.web_filechooser);
  163. ViewGroup viewGroup = (ViewGroup) normalView.getParent();
  164. viewGroup.removeView(normalView);
  165. viewGroup.addView(view);
  166. myVideoView = view;
  167. myNormalView = normalView;
  168. callback = customViewCallback;
  169. }
  170. @Override
  171. public void onHideCustomView() {
  172. if (callback != null) {
  173. callback.onCustomViewHidden();
  174. callback = null;
  175. }
  176. if (myVideoView != null) {
  177. ViewGroup viewGroup = (ViewGroup) myVideoView.getParent();
  178. viewGroup.removeView(myVideoView);
  179. viewGroup.addView(myNormalView);
  180. }
  181. }
  182. @Override
  183. public boolean onJsAlert(WebView arg0, String arg1, String arg2,
  184. JsResult arg3) {
  185. /**
  186. * 这里写入你自定义的window alert
  187. */
  188. return super.onJsAlert(null, arg1, arg2, arg3);
  189. }
  190. });
  191. mWebView.setDownloadListener(new DownloadListener() {
  192. @Override
  193. public void onDownloadStart(String arg0, String arg1, String arg2,
  194. String arg3, long arg4) {
  195. TbsLog.d(TAG, "url: " + arg0);
  196. new AlertDialog.Builder(BrowserActivity.this)
  197. .setTitle("allow to download?")
  198. .setPositiveButton("yes",
  199. new DialogInterface.OnClickListener() {
  200. @Override
  201. public void onClick(DialogInterface dialog,
  202. int which) {
  203. Toast.makeText(
  204. BrowserActivity.this,
  205. "fake message: i'll download...",
  206. Toast.LENGTH_SHORT).show();
  207. }
  208. })
  209. .setNegativeButton("no",
  210. new DialogInterface.OnClickListener() {
  211. @Override
  212. public void onClick(DialogInterface dialog,
  213. int which) {
  214. // TODO Auto-generated method stub
  215. Toast.makeText(
  216. BrowserActivity.this,
  217. "fake message: refuse download...",
  218. Toast.LENGTH_SHORT).show();
  219. }
  220. })
  221. .setOnCancelListener(
  222. new DialogInterface.OnCancelListener() {
  223. @Override
  224. public void onCancel(DialogInterface dialog) {
  225. // TODO Auto-generated method stub
  226. Toast.makeText(
  227. BrowserActivity.this,
  228. "fake message: refuse download...",
  229. Toast.LENGTH_SHORT).show();
  230. }
  231. }).show();
  232. }
  233. });
  234. WebSettings webSetting = mWebView.getSettings();
  235. webSetting.setAllowFileAccess(true);
  236. webSetting.setLayoutAlgorithm(LayoutAlgorithm.NARROW_COLUMNS);
  237. webSetting.setSupportZoom(true);
  238. webSetting.setBuiltInZoomControls(true);
  239. webSetting.setUseWideViewPort(true);
  240. webSetting.setSupportMultipleWindows(false);
  241. // webSetting.setLoadWithOverviewMode(true);
  242. webSetting.setAppCacheEnabled(true);
  243. // webSetting.setDatabaseEnabled(true);
  244. webSetting.setDomStorageEnabled(true);
  245. webSetting.setJavaScriptEnabled(true);
  246. webSetting.setGeolocationEnabled(true);
  247. webSetting.setMixedContentMode(android.webkit.WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
  248. webSetting.setAppCacheMaxSize(Long.MAX_VALUE);
  249. webSetting.setAppCachePath(this.getDir("appcache", 0).getPath());
  250. webSetting.setDatabasePath(this.getDir("databases", 0).getPath());
  251. webSetting.setGeolocationDatabasePath(this.getDir("geolocation", 0)
  252. .getPath());
  253. // webSetting.setPageCacheCapacity(IX5WebSettings.DEFAULT_CACHE_CAPACITY);
  254. webSetting.setPluginState(WebSettings.PluginState.ON_DEMAND);
  255. // webSetting.setRenderPriority(WebSettings.RenderPriority.HIGH);
  256. // webSetting.setPreFectch(true);
  257. long time = System.currentTimeMillis();
  258. if (mIntentUrl == null) {
  259. mWebView.loadUrl(weiuri);
  260. } else {
  261. mWebView.loadUrl(mIntentUrl.toString());
  262. }
  263. TbsLog.d("time-cost", "cost time: "
  264. + (System.currentTimeMillis() - time));
  265. CookieSyncManager.createInstance(this);
  266. CookieSyncManager.getInstance().sync();
  267. //H5界面加载进度监听
  268. mWebView.setWebChromeClient(new WebChromeClient() {
  269. @Override
  270. public void onProgressChanged(WebView view, int newProgress) {
  271. super.onProgressChanged(view, newProgress);
  272. }
  273. // For Android < 5.0
  274. public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
  275. openFileChooserImpl(uploadMsg);
  276. }
  277. // For Android => 5.0
  278. public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> uploadMsg,
  279. WebChromeClient.FileChooserParams fileChooserParams) {
  280. onenFileChooseImpleForAndroid(uploadMsg);
  281. return true;
  282. }
  283. });
  284. return null;
  285. }
  286. /**
  287. * android 5.0 以下开启图片选择(原生)
  288. * <p>
  289. * 可以自己改图片选择框架。
  290. */
  291. private void openFileChooserImpl(ValueCallback<Uri> uploadMsg) {
  292. uploadFile = uploadMsg;
  293. Intent i = new Intent(Intent.ACTION_GET_CONTENT);
  294. i.addCategory(Intent.CATEGORY_OPENABLE);
  295. i.setType("image/*");
  296. startActivityForResult(Intent.createChooser(i, "File Chooser"), FILE_CHOOSER_RESULT_CODE);
  297. }
  298. /**
  299. * android 5.0(含) 以上开启图片选择(原生)
  300. * <p>
  301. * 可以自己改图片选择框架。
  302. */
  303. private void onenFileChooseImpleForAndroid(ValueCallback<Uri[]> filePathCallback) {
  304. mUploadMessageForAndroid5 = filePathCallback;
  305. Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
  306. contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
  307. contentSelectionIntent.setType("image/*");
  308. Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
  309. chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
  310. chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
  311. startActivityForResult(chooserIntent, FILE_CHOOSER_RESULT_CODE_FOR_ANDROID_5);
  312. }
  313. private void initBtnListenser() {
  314. mBack = (ImageButton) findViewById(R.id.btnBack1);
  315. mForward = (ImageButton) findViewById(R.id.btnForward1);
  316. mExit = (ImageButton) findViewById(R.id.btnExit1);
  317. mHome = (ImageButton) findViewById(R.id.btnHome1);
  318. mGo = (Button) findViewById(R.id.btnGo1);
  319. mUrl = (EditText) findViewById(R.id.editUrl1);
  320. mMore = (ImageButton) findViewById(R.id.btnMore);
  321. if (Integer.parseInt(android.os.Build.VERSION.SDK) >= 16) {
  322. mBack.setAlpha(disable);
  323. mForward.setAlpha(disable);
  324. mHome.setAlpha(disable);
  325. }
  326. }
  327. boolean[] m_selected = new boolean[]{true, true, true, true, false,
  328. false, true};
  329. @Override
  330. public boolean onKeyDown(int keyCode, KeyEvent event) {
  331. if (keyCode == KeyEvent.KEYCODE_BACK) {
  332. if (mWebView != null && mWebView.canGoBack()) {
  333. mWebView.goBack();
  334. if (Integer.parseInt(android.os.Build.VERSION.SDK) >= 16)
  335. changGoForwardButton(mWebView);
  336. return true;
  337. } else
  338. return super.onKeyDown(keyCode, event);
  339. }
  340. return super.onKeyDown(keyCode, event);
  341. }
  342. @Override
  343. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  344. TbsLog.d(TAG, "onActivityResult, requestCode:" + requestCode
  345. + ",resultCode:" + resultCode);
  346. if (resultCode == RESULT_OK) {
  347. switch (requestCode) {
  348. case 0:
  349. Uri result;
  350. if (null != uploadFile) {
  351. result = data == null || resultCode != RESULT_OK ? null
  352. : data.getData();
  353. uploadFile.onReceiveValue(result);
  354. uploadFile = null;
  355. }
  356. break;
  357. case FILE_CHOOSER_RESULT_CODE: //android 5.0以下 选择图片回调
  358. result = (intent == null || resultCode != Activity.RESULT_OK) ? null : intent.getData();
  359. if (null == uploadFile)
  360. return;
  361. uploadFile.onReceiveValue(result);
  362. uploadFile = null;
  363. break;
  364. case FILE_CHOOSER_RESULT_CODE_FOR_ANDROID_5: //android 5.0(含) 以上 选择图片回调
  365. result = data.getData();
  366. if (null == mUploadMessageForAndroid5)
  367. return;
  368. if (result != null) {
  369. mUploadMessageForAndroid5.onReceiveValue(new Uri[]{result});
  370. } else {
  371. mUploadMessageForAndroid5.onReceiveValue(new Uri[]{});
  372. }
  373. mUploadMessageForAndroid5 = null;
  374. break;
  375. default:
  376. break;
  377. }
  378. } else if (resultCode == RESULT_CANCELED) {
  379. if (null != uploadFile) {
  380. uploadFile.onReceiveValue(null);
  381. uploadFile = null;
  382. }
  383. }
  384. }
  385. @Override
  386. protected void onNewIntent(Intent intent) {
  387. if (intent == null || mWebView == null || intent.getData() == null)
  388. return;
  389. mWebView.loadUrl(intent.getData().toString());
  390. }
  391. @Override
  392. protected void onDestroy() {
  393. if (mTestHandler != null)
  394. mTestHandler.removeCallbacksAndMessages(null);
  395. if (mWebView != null)
  396. mWebView.destroy();
  397. super.onDestroy();
  398. }
  399. public static final int MSG_OPEN_TEST_URL = 0;
  400. public static final int MSG_INIT_UI = 1;
  401. private final int mUrlStartNum = 0;
  402. private int mCurrentUrl = mUrlStartNum;
  403. private Handler mTestHandler = new Handler() {
  404. @Override
  405. public void handleMessage(Message msg) {
  406. switch (msg.what) {
  407. case MSG_OPEN_TEST_URL:
  408. if (!mNeedTestPage) {
  409. return;
  410. }
  411. String testUrl = "file:///sdcard/outputHtml/html/"
  412. + Integer.toString(mCurrentUrl) + ".html";
  413. if (mWebView != null) {
  414. mWebView.loadUrl(testUrl);
  415. }
  416. mCurrentUrl++;
  417. break;
  418. case MSG_INIT_UI:
  419. init();
  420. break;
  421. }
  422. super.handleMessage(msg);
  423. }
  424. };
  425. private void startAlipayActivity(String url) {
  426. Intent intent;
  427. try {
  428. intent = Intent.parseUri(url,
  429. Intent.URI_INTENT_SCHEME);
  430. intent.addCategory(Intent.CATEGORY_BROWSABLE);
  431. intent.setComponent(null);
  432. startActivity(intent);
  433. } catch (Exception e) {
  434. e.printStackTrace();
  435. }
  436. }
  437. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/686283
推荐阅读
相关标签
  

闽ICP备14008679号