• MyX5TbsDemo【体验腾讯浏览服务Android SDK (完整版)】


    版权声明:本文为HaiyuKing原创文章,转载请注明出处!

    前言

    按照官网上的说明:可独立下载x5内核,也可共享使用微信或手Q的x5内核。

    本Demo在引用腾讯X5内核的基础上进行了封装。参考《MyWebViewDemo【封装Webview常用配置和选择文件、打开相机、录音、打开本地相册的用法】

    使用TbsReaderView预览文件功能,请参考《MyX5TbsPlusDemo【体验腾讯浏览服务Android SDK (TbsPlus 版)】

    效果图

     

    代码分析

    X5WebView : 对腾讯X5内核的webview进行了封装;

    BrowserActivity:用于展现打开普通网页;

    FilechooserActivity : 用于展示在web端<input type=text>的标签被选择之后,文件选择器的制作和生成;

    FullScreenActivity : 用于演示X5webview实现视频的全屏播放功能 其中注意 X5的默认全屏方式 与 android 系统的全屏方式

    注意:

    X5WebView 继承 WebView(指的是X5内核的webview,所以import com.tencent.smtt.sdk.WebView;)

    X5WebViewClient 继承 WebViewClient(import com.tencent.smtt.sdk.WebViewClient;

    X5WebChromeClient 继承 WebChromeClient(import com.tencent.smtt.sdk.WebChromeClient;

    使用步骤

    一、项目组织结构图

    注意事项:

    1、  导入类文件后需要change包名以及重新import R文件路径

    2、  Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖

    二、导入步骤

    1、下载sdk

    下载地址:https://x5.tencent.com/tbs/sdk.html

    下载的文件解压后如下:【接入文档很有用】

    2、将jar文件导入项目中

    参考《【Android Studio安装部署系列】十七、Android studio引用第三方库、jar、so、arr文件

    3、实现支持64位手机加载X5

    将SDK接入示例-Android Studio文件中的demo项目的jniLibs目录复制到项目的main目录下【如果项目的main目录中已经存在jniLibs文件夹,则只需要把so文件复制到相应armeabi目录下】

    在build.gradle文件中添加以下代码

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 27
        defaultConfig {
            applicationId "com.why.project.myx5tbsdemo"
            minSdkVersion 16
            targetSdkVersion 27
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    
            //腾讯浏览服务实现支持64位手机加载X5
            // Specifies the ABI configurations of your native
            // libraries Gradle should build and package with your APK.
            ndk {
                abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
            }
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation 'com.android.support:appcompat-v7:27.1.1'
        implementation 'com.android.support.constraint:constraint-layout:1.1.2'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'com.android.support.test:runner:1.0.2'
        androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    }

    如果配置后编译报错,那么需要在gradle.properties文件中加上Android.useDeprecatedNdk=true;【一般不需要,本demo中没有添加】

    4、在AndroidManifest.xml中声明权限

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              package="com.why.project.myx5tbsdemo">
    
        <!-- ======================腾讯浏览服务========================== -->
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        <uses-permission android:name="android.permission.READ_SETTINGS" />
        <uses-permission android:name="android.permission.WRITE_SETTINGS" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    
        <!-- 硬件加速对X5视频播放非常重要,建议开启(如果有网页视频播放的话建议开启) -->
        <uses-permission android:name="android.permission.GET_TASKS" />
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
    
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
        </application>
    
    </manifest>

    5、在自定义Application里面初始化X5内核

    package com.why.project.myx5tbsdemo;
    
    import android.app.Application;
    import android.content.Context;
    import android.util.Log;
    
    import com.tencent.smtt.sdk.QbSdk;
    
    /**
     * Created by HaiyuKing
     * Used 在Application里面初始化X5内核
     */
    
    public class MyApplication extends Application {
    
        /**系统上下文*/
        private static Context mAppContext;
    
        @Override
        public void onCreate() {
            // TODO Auto-generated method stub
            super.onCreate();
            mAppContext = getApplicationContext();
    
            //配置腾讯浏览服务
            initQbSdk();
    
        }
    
        /**获取系统上下文*/
        public static Context getAppContext()
        {
            return mAppContext;
        }
    
        private void initQbSdk() {
            //搜集本地tbs内核信息并上报服务器,服务器返回结果决定使用哪个内核。
            QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() {
                @Override
                public void onViewInitFinished(boolean arg0) {
                    // TODO Auto-generated method stub
                    //x5內核初始化完成的回调,为true表示x5内核加载成功,否则表示x5内核加载失败,会自动切换到系统内核。
                    Log.d("app", " onViewInitFinished is " + arg0);
                }
                @Override
                public void onCoreInitFinished() {
                    // TODO Auto-generated method stub
                }
            };
            //x5内核初始化接口
            QbSdk.initX5Environment(mAppContext,  cb);
        }
    }

    6、在AndroidManifest.xml文件中声明这个自定义的application

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              package="com.why.project.myx5tbsdemo">
    
        <!-- ======================腾讯浏览服务========================== -->
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        <uses-permission android:name="android.permission.READ_SETTINGS" />
        <uses-permission android:name="android.permission.WRITE_SETTINGS" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    
        <!-- 硬件加速对X5视频播放非常重要,建议开启(如果有网页视频播放的话建议开启) -->
        <uses-permission android:name="android.permission.GET_TASKS" />
    
        <application
            android:name=".MyApplication"
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
    
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
        </application>
    
    </manifest>

    到这里,基本上将腾讯浏览服务X5内核引入到项目中了。不过本Demo对X5WebView进行了封装,所以还需要进行下面的操作。

    二、下面导入自己封装的X5WebView

    1、将customwebview包复制到项目中

    2、将x5webview_progress_dialog_img_drawable.xml复制到项目中

    <?xml version="1.0" encoding="utf-8"?>
    <!-- WebView使用的进度加载对话框进度圆圈 -->
    <animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
        android:drawable="@drawable/x5webview_progress_dialog_img"
        android:pivotX="50%"
        android:pivotY="50%"
        android:fromDegrees="0.0"
        android:toDegrees="360.0"
        android:repeatMode="restart"
         />
    x5webview_progress_dialog_img_drawable.xml

    3、将x5webview_progress_dialog_img.png图片复制到项目中

    4、将x5webview_dialog_webviewprogress.xml复制到项目中

    <?xml version="1.0" encoding="utf-8"?>
    <!-- WebView使用的进度加载对话框布局文件 -->
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/dialog_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
        <!-- 自定义圆形进度条 -->
        <!-- android:indeterminateDrawable自定义动画图标 -->
        <ProgressBar
            android:id="@+id/loadProgressBar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="5dp"
            android:indeterminateDrawable="@drawable/x5webview_progress_dialog_img_drawable"
            />
    
    </RelativeLayout>
    x5webview_dialog_webviewprogress.xml

    5、在styles.xml文件中添加以下代码

    <resources>
    
        <!-- Base application theme. -->
        <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
            <!-- Customize your theme here. -->
            <item name="colorPrimary">@color/colorPrimary</item>
            <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
            <item name="colorAccent">@color/colorAccent</item>
        </style>
    
        <!-- ==================X5Webview========网页加载时的进度对话框========================== -->
        <style name="x5webview_loading_style" parent="android:style/Theme.Dialog">
            <!-- Dialog的windowFrame框为无 -->
            <item name="android:windowFrame">@null</item>
            <!-- 是否显示title -->
            <item name="android:windowNoTitle">true</item>
            <!-- 是否浮现在activity之上 -->
            <item name="android:windowIsFloating">true</item>
            <!-- 设置dialog的背景:#00000000透明色 -->
            <item name="android:windowBackground">@android:color/transparent</item>
            <!-- 半透明 -->
            <item name="android:windowIsTranslucent">true</item>
            <!-- 背景变灰:整个屏幕变灰,配合setCanceledOnTouchOutside(false) -->
            <item name="android:backgroundDimEnabled">false</item>
            <!-- 对话框是否有遮盖 -->
            <item name="android:windowContentOverlay">@null</item>
        </style>
    
    </resources>

    6、在AndroidManifest.xml中添加以下代码【因为有重复的权限,所以注释掉了】

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              package="com.why.project.myx5tbsdemo">
    
        <!-- ======================腾讯浏览服务========================== -->
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        <uses-permission android:name="android.permission.READ_SETTINGS" />
        <uses-permission android:name="android.permission.WRITE_SETTINGS" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    
        <!-- 硬件加速对X5视频播放非常重要,建议开启(如果有网页视频播放的话建议开启) -->
        <uses-permission android:name="android.permission.GET_TASKS" />
    
        <!-- ======================(X5WebView)========================== -->
        <!-- 允许程序打开网络套接字 -->
        <!--<uses-permission android:name="android.permission.INTERNET"/>-->
        <!-- ======================拍照用到的========================== -->
        <uses-permission android:name="android.permission.CAMERA" />
        <!-- ======================录音用到的========================== -->
        <uses-permission android:name="android.permission.RECORD_AUDIO" />
        <!-- 向SD卡写入数据权限 -->
        <!--<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />-->
        <!--<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />-->
    
        <application
            android:name=".MyApplication"
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
    
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
        </application>
    
    </manifest>

    7、将assets文件夹复制到项目中

    <html>
        <head>
            <meta content="text/html; charset=utf-8" http-equiv="content-type">
            <meta http-equiv="keywords" content="测试">
            <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
            <title>
                webview
            </title>
        </head>
        
        <body>
            <p>
                <input type="file" value="打开文件" />
            </p>
    
            <p>
                点击下面的按钮,获取的文件路径:
            </p>
            <p>
                <input type="text" id="filePath" value="文件路径" style="100%"/>
            </p>
            <p>
                <input type="button" id="openRecord" value="打开录音" onclick="window.androidMethod.openRecord();"/>
            </p>
            <p>
                <input type="button" id="takePicture" value="打开相机" onclick="window.androidMethod.takePicture();"/>
            </p>
            <p>
                <input type="button" id="choosePic" value="打开本地相册" onclick="window.androidMethod.choosePic();"/>
            </p>
            <p>
                <a href='tel:10010'>拨打电话:10010</a>
            </p>
        </body>
        <script>
            //打开录音、打开相机、打开本地相册,选择文件后返回的路径
            function setInputText(urlPath){
                document.getElementById("filePath").value = urlPath;
            }
        </script>
    
    </html>
    demo.html

    三、因为demo中使用到获取手机本地文件的权限和调用相机功能,所以需要申请运行时权限和适配7.0FIleProvider功能。

    0-1、申请运行时权限,参考《Android6.0运行时权限(基于RxPermission开源库)

    0-2、适配Android7.0FileProvider功能,参考《AppUtils【获取手机的信息和应用版本号、安装apk】

    三、使用方法

    1、打开普通网页,参考BrowserActivity

    package com.why.project.myx5tbsdemo;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.KeyEvent;
    import android.widget.FrameLayout;
    
    import com.why.project.myx5tbsdemo.customwebview.x5webview.X5WebView;
    
    /**
     * Created by HaiyuKing
     * Used 用于展现打开普通网页;
     */
    
    public class BrowserActivity extends AppCompatActivity {
        private static final String TAG = BrowserActivity.class.getSimpleName();
    
        //内容显示区域
        private FrameLayout center_layout;
        private X5WebView mX5WebView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_x5webview);
    
            initViews();
            initDatas();
            initEvents();
        }
    
        @Override
        public void onDestroy() {
            if (mX5WebView != null) {
                mX5WebView.removeAllViews();
                mX5WebView.destroy();
            }
    
            super.onDestroy();
        }
    
    
        private void initViews() {
            //内容显示区域
            center_layout = (FrameLayout) findViewById(R.id.center_layout);
    
            mX5WebView = new X5WebView(this, null);
            center_layout.addView(mX5WebView, new FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.MATCH_PARENT,
                    FrameLayout.LayoutParams.MATCH_PARENT));
        }
    
        private void initDatas() {
            mX5WebView.setCanBackPreviousPage(true, BrowserActivity.this);//设置可返回上一页
    
            mX5WebView.loadUrl("http://www.baidu.com");
        }
    
        private void initEvents() {
    
        }
    
        /**
         * 截取返回软键事件【在activity中写,不能在自定义的X5Webview中】
         */
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
    
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                if ((keyCode == KeyEvent.KEYCODE_BACK) && mX5WebView.canGoBack()) {
                    mX5WebView.goBack();
                    return true;
                } else {
                    finish();
                    return true;
                }
            }
            return super.onKeyDown(keyCode, event);
        }
    }

    布局文件【这三个演示Activity都是使用这个布局文件】

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <!-- 内容区域 -->
        <FrameLayout
            android:id="@+id/center_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
        </FrameLayout>
    
    </RelativeLayout>

    2、展示在web端<input type=text>的标签被选择之后,文件选择器的制作和生成,参考FilechooserActivity

    package com.why.project.myx5tbsdemo;
    
    import android.annotation.TargetApi;
    import android.app.Activity;
    import android.content.Intent;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.KeyEvent;
    import android.widget.FrameLayout;
    import android.widget.Toast;
    
    import com.tencent.smtt.sdk.ValueCallback;
    import com.why.project.myx5tbsdemo.customwebview.utils.GetPathFromUri4kitkat;
    import com.why.project.myx5tbsdemo.customwebview.utils.WebviewGlobals;
    import com.why.project.myx5tbsdemo.customwebview.x5webview.X5WebView;
    import com.why.project.myx5tbsdemo.customwebview.x5webview.X5WebViewJSInterface;
    
    import java.io.File;
    
    /**
     * Created by HaiyuKing
     * Used 用于展示在web端<input type=text>的标签被选择之后,文件选择器的制作和生成
     */
    
    public class FilechooserActivity extends AppCompatActivity {
        private static final String TAG = FilechooserActivity.class.getSimpleName();
    
        //内容显示区域
        private FrameLayout center_layout;
        private X5WebView mX5WebView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_x5webview);
    
            initViews();
            initDatas();
            initEvents();
        }
    
        @Override
        public void onDestroy() {
            if (mX5WebView != null) {
                mX5WebView.removeAllViews();
                mX5WebView.destroy();
            }
    
            super.onDestroy();
        }
    
    
        private void initViews() {
            //内容显示区域
            center_layout = (FrameLayout) findViewById(R.id.center_layout);
    
            mX5WebView = new X5WebView(this, null);
            center_layout.addView(mX5WebView, new FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.MATCH_PARENT,
                    FrameLayout.LayoutParams.MATCH_PARENT));
        }
    
        private void initDatas() {
            mX5WebView.setCanBackPreviousPage(true, FilechooserActivity.this);//设置可返回上一页
    
            mX5WebView.loadLocalUrl("demo.html");
        }
    
        private void initEvents() {
    
        }
    
        /**
         * 截取返回软键事件【在activity中写,不能在自定义的X5Webview中】
         */
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
    
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                if ((keyCode == KeyEvent.KEYCODE_BACK) && mX5WebView.canGoBack()) {
                    mX5WebView.goBack();
                    return true;
                } else {
                    finish();
                    return true;
                }
            }
            return super.onKeyDown(keyCode, event);
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            // TODO Auto-generated method stub
            super.onActivityResult(requestCode, resultCode, data);
            Log.w(TAG, "{onActivityResult}resultCode="+resultCode);
            Log.w(TAG, "{onActivityResult}requestCode="+requestCode);
    
            if (resultCode == Activity.RESULT_OK) {
                //webview界面调用打开本地文件管理器选择文件的回调
                if (requestCode == WebviewGlobals.CHOOSE_FILE_REQUEST_CODE ) {
                    Uri result = data == null ? null : data.getData();
                    Log.w(TAG,"{onActivityResult}文件路径地址:" + result.toString());
    
                    //如果mUploadMessage或者mUploadCallbackAboveL不为空,代表是触发input[type]类型的标签
                    if (null != mX5WebView.getX5WebChromeClient().getmUploadMessage() || null != mX5WebView.getX5WebChromeClient().getmUploadCallbackAboveL()) {
                        if (mX5WebView.getX5WebChromeClient().getmUploadCallbackAboveL() != null) {
                            onActivityResultAboveL(requestCode, data);//5.0++
                        } else if (mX5WebView.getX5WebChromeClient().getmUploadMessage() != null) {
                            mX5WebView.getX5WebChromeClient().getmUploadMessage().onReceiveValue(result);//将文件路径返回去,填充到input中
                            mX5WebView.getX5WebChromeClient().setmUploadMessage(null);
                        }
                    }else{
                        //此处代码是处理通过js方法触发的情况
                        Log.w(TAG,"{onActivityResult}文件路径地址(js):" + result.toString());
                        String filePath = GetPathFromUri4kitkat.getPath(FilechooserActivity.this,Uri.parse(result.toString()));
    
                        //修改网页输入框文本【无法通过evaluateJavascript方式执行js方法,需要特殊处理】
                        setUrlPathInput(mX5WebView,"打开本地相册:" + filePath);
                    }
                }
                //因为拍照指定了路径,所以data值为null
                if(requestCode == WebviewGlobals.CAMERA_REQUEST_CODE){
                    File pictureFile = new File(X5WebViewJSInterface.mCurrentPhotoPath);
    
                    Uri uri = Uri.fromFile(pictureFile);
                    Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                    intent.setData(uri);
                    FilechooserActivity.this.sendBroadcast(intent);  // 这里我们发送广播让MediaScanner 扫描我们制定的文件
                    // 这样在系统的相册中我们就可以找到我们拍摄的照片了【但是这样一来,就会执行MediaScanner服务中onLoadFinished方法,所以需要注意】
    
                    //拍照
    //                String fileName = FileUtils.getFileName(X5WebViewJSInterface.mCurrentPhotoPath);
                    Log.e(TAG,"WebViewJSInterface.mCurrentPhotoPath="+X5WebViewJSInterface.mCurrentPhotoPath);
    
                    //修改网页输入框文本【无法通过evaluateJavascript方式执行js方法,需要特殊处理】
                    setUrlPathInput(mX5WebView,"打开相机:" + X5WebViewJSInterface.mCurrentPhotoPath);
                }
    
                //录音
                if(requestCode == WebviewGlobals.RECORD_REQUEST_CODE){
                    Uri result = data == null ? null : data.getData();
                    Log.w(TAG,"录音文件路径地址:" + result.toString());//录音文件路径地址:content://media/external/audio/media/111
    
                    String filePath = GetPathFromUri4kitkat.getPath(FilechooserActivity.this,Uri.parse(result.toString()));
                    Log.w(TAG,"录音文件路径地址:" + filePath);
    
                    //修改网页输入框文本【无法通过evaluateJavascript方式执行js方法,需要特殊处理】
                    setUrlPathInput(mX5WebView,"打开录音:" + filePath);
                }
            } else if(resultCode == RESULT_CANCELED){//resultCode == RESULT_CANCELED 解决不选择文件,直接返回后无法再次点击的问题
                if (mX5WebView.getX5WebChromeClient().getmUploadMessage() != null) {
                    mX5WebView.getX5WebChromeClient().getmUploadMessage().onReceiveValue(null);
                    mX5WebView.getX5WebChromeClient().setmUploadMessage(null);
                }
                if (mX5WebView.getX5WebChromeClient().getmUploadCallbackAboveL() != null) {
                    mX5WebView.getX5WebChromeClient().getmUploadCallbackAboveL().onReceiveValue(null);
                    mX5WebView.getX5WebChromeClient().setmUploadCallbackAboveL(null);
                }
            }
        }
    
        //5.0以上版本,由于api不一样,要单独处理
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        private void onActivityResultAboveL(int requestCode, Intent data) {
    
            if (mX5WebView.getX5WebChromeClient().getmUploadCallbackAboveL() == null) {
                return;
            }
            Uri result = null;
            if (requestCode == WebviewGlobals.CHOOSE_FILE_REQUEST_CODE) {//打开本地文件管理器选择图片
                result = data.getData();
            } else if (requestCode == WebviewGlobals.CAMERA_REQUEST_CODE) {//调用相机拍照
                File pictureFile = new File(X5WebViewJSInterface.mCurrentPhotoPath);
    
                Uri uri = Uri.fromFile(pictureFile);
                Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                intent.setData(uri);
                FilechooserActivity.this.sendBroadcast(intent);  // 这里我们发送广播让MediaScanner 扫描我们制定的文件
                // 这样在系统的相册中我们就可以找到我们拍摄的照片了【但是这样一来,就会执行MediaScanner服务中onLoadFinished方法,所以需要注意】
    
                result = Uri.fromFile(pictureFile);
            }
            Log.w(TAG,"{onActivityResultAboveL}文件路径地址:"+result.toString());
            mX5WebView.getX5WebChromeClient().getmUploadCallbackAboveL().onReceiveValue(new Uri[]{result});//将文件路径返回去,填充到input中
            mX5WebView.getX5WebChromeClient().setmUploadCallbackAboveL(null);
            return;
        }
    
        //设置网页上的文件路径输入框文本
        private void setUrlPathInput(X5WebView webView, String urlPath) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                webView.evaluateJavascript("setInputText('"+ urlPath +"')", new ValueCallback<String>() {
                    @Override
                    public void onReceiveValue(String value) {
                        Log.i(TAG, "onReceiveValue value=" + value);
                    }});
            }else{
                Toast.makeText(FilechooserActivity.this,"当前版本号小于19,无法支持evaluateJavascript,需要使用第三方库JSBridge", Toast.LENGTH_SHORT).show();
            }
        }
    }

    3、演示X5webview实现视频的全屏播放功能 ,参考FullScreenActivity

    package com.why.project.myx5tbsdemo;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.KeyEvent;
    import android.widget.FrameLayout;
    import android.widget.Toast;
    
    import com.why.project.myx5tbsdemo.customwebview.x5webview.X5WebView;
    
    /**
     * Created by HaiyuKing
     * Used 用于演示X5webview实现视频的全屏播放功能 其中注意 X5的默认全屏方式 与 android 系统的全屏方式
     */
    
    public class FullScreenActivity extends AppCompatActivity {
        private static final String TAG = FullScreenActivity.class.getSimpleName();
    
        //内容显示区域
        private FrameLayout center_layout;
        private X5WebView mX5WebView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_x5webview);
    
            initViews();
            initDatas();
            initEvents();
        }
    
        @Override
        public void onDestroy() {
            if (mX5WebView != null) {
                mX5WebView.removeAllViews();
                mX5WebView.destroy();
            }
    
            super.onDestroy();
        }
    
    
        private void initViews() {
            //内容显示区域
            center_layout = (FrameLayout) findViewById(R.id.center_layout);
    
            mX5WebView = new X5WebView(this, null);
            center_layout.addView(mX5WebView, new FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.MATCH_PARENT,
                    FrameLayout.LayoutParams.MATCH_PARENT));
        }
    
        private void initDatas() {
            mX5WebView.setCanBackPreviousPage(true, FullScreenActivity.this);//设置可返回上一页
    
            enablePageVideoFunc();//设置视频播放样式
    
            mX5WebView.loadUrl("http://live.hkstv.hk.lxdns.com/live/hks/playlist.m3u8");
        }
    
        private void initEvents() {
    
        }
    
        /**
         * 截取返回软键事件【在activity中写,不能在自定义的X5Webview中】
         */
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
    
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                if ((keyCode == KeyEvent.KEYCODE_BACK) && mX5WebView.canGoBack()) {
                    mX5WebView.goBack();
                    return true;
                } else {
                    finish();
                    return true;
                }
            }
            return super.onKeyDown(keyCode, event);
        }
    
        //恢复webkit初始状态
        private void disableX5FullscreenFunc() {
            if (mX5WebView.getX5WebViewExtension() != null) {
                Toast.makeText(this, "恢复webkit初始状态", Toast.LENGTH_LONG).show();
                Bundle data = new Bundle();
                data.putBoolean("standardFullScreen", true);// true表示标准全屏,会调起onShowCustomView(),false表示X5全屏;不设置默认false,
                data.putBoolean("supportLiteWnd", false);// false:关闭小窗;true:开启小窗;不设置默认true,
                data.putInt("DefaultVideoScreen", 2);// 1:以页面内开始播放,2:以全屏开始播放;不设置默认:1
    
                mX5WebView.getX5WebViewExtension().invokeMiscMethod("setVideoParams", data);
                //设置WebView是否通过手势触发播放媒体,默认是true,需要手势触发。
                mX5WebView.getSettings().setMediaPlaybackRequiresUserGesture(false);
                //接口禁止(直接或反射)调用,避免视频画面无法显示
                mX5WebView.setDrawingCacheEnabled(true);
            }
        }
    
        //开启X5全屏播放模式
        private void enableX5FullscreenFunc() {
    
            if (mX5WebView.getX5WebViewExtension() != null) {
                Toast.makeText(this, "开启X5全屏播放模式", Toast.LENGTH_LONG).show();
                Bundle data = new Bundle();
    
                data.putBoolean("standardFullScreen", false);// true表示标准全屏,false表示X5全屏;不设置默认false,
    
                data.putBoolean("supportLiteWnd", false);// false:关闭小窗;true:开启小窗;不设置默认true,
    
                data.putInt("DefaultVideoScreen", 2);// 1:以页面内开始播放,2:以全屏开始播放;不设置默认:1
    
                mX5WebView.getX5WebViewExtension().invokeMiscMethod("setVideoParams", data);
                //设置WebView是否通过手势触发播放媒体,默认是true,需要手势触发。
                mX5WebView.getSettings().setMediaPlaybackRequiresUserGesture(false);
                //接口禁止(直接或反射)调用,避免视频画面无法显示
                mX5WebView.setDrawingCacheEnabled(true);
            }
        }
    
        //开启小窗模式
        private void enableLiteWndFunc() {
            if (mX5WebView.getX5WebViewExtension() != null) {
                Toast.makeText(this, "开启小窗模式", Toast.LENGTH_LONG).show();
                Bundle data = new Bundle();
    
                data.putBoolean("standardFullScreen", false);// true表示标准全屏,会调起onShowCustomView(),false表示X5全屏;不设置默认false,
    
                data.putBoolean("supportLiteWnd", true);// false:关闭小窗;true:开启小窗;不设置默认true,
    
                data.putInt("DefaultVideoScreen", 2);// 1:以页面内开始播放,2:以全屏开始播放;不设置默认:1
    
                mX5WebView.getX5WebViewExtension().invokeMiscMethod("setVideoParams", data);
                //设置WebView是否通过手势触发播放媒体,默认是true,需要手势触发。
                mX5WebView.getSettings().setMediaPlaybackRequiresUserGesture(false);
                //接口禁止(直接或反射)调用,避免视频画面无法显示
                mX5WebView.setDrawingCacheEnabled(true);
            }
        }
    
        //页面内全屏播放模式
        private void enablePageVideoFunc() {
            if (mX5WebView.getX5WebViewExtension() != null) {
                Toast.makeText(this, "页面内全屏播放模式", Toast.LENGTH_LONG).show();
                Bundle data = new Bundle();
    
                data.putBoolean("standardFullScreen", false);// true表示标准全屏,会调起onShowCustomView(),false表示X5全屏;不设置默认false,
    
                data.putBoolean("supportLiteWnd", false);// false:关闭小窗;true:开启小窗;不设置默认true,
    
                data.putInt("DefaultVideoScreen", 1);// 1:以页面内开始播放,2:以全屏开始播放;不设置默认:1
    
                mX5WebView.getX5WebViewExtension().invokeMiscMethod("setVideoParams", data);
                //设置WebView是否通过手势触发播放媒体,默认是true,需要手势触发。
                mX5WebView.getSettings().setMediaPlaybackRequiresUserGesture(false);
                //接口禁止(直接或反射)调用,避免视频画面无法显示
                mX5WebView.setDrawingCacheEnabled(true);
            }
        }
    
    }

    混淆配置

    参考资料

    Android在项目中接入腾讯TBS浏览器WebView的教程与注意的地方

    项目demo下载地址

    https://github.com/haiyuKing/MyX5TbsDemo

  • 相关阅读:
    几款网络测试工具总结
    Linux安装telnet
    Linux下iptables 禁止端口和开放端口
    mysql创建某个数据库中的某张表 只读用户
    查看nginx版本号的几种方法
    Ngxtop-Nginx日志实时分析利器
    Nginx监控运维
    oracle经典书籍推荐
    华为典型局域网组网案例介绍(1)
    技术说明 路由器是如何工作的呢? 一个简单的解释
  • 原文地址:https://www.cnblogs.com/whycxb/p/9308412.html
Copyright © 2020-2023  润新知