1. 程式人生 > 程式設計 >Android整合騰訊X5實現文件瀏覽功能

Android整合騰訊X5實現文件瀏覽功能

Android內部沒有控制元件來直接顯示文件,跳轉WPS或其他第三方文件App體驗性不好,使用騰訊X5核心能很好的解決的這一問題。

一、下載騰訊X5核心

1.前往https://x5.tencent.com/下載Android的核心,新版本的騰訊X5可以直接在bulid.gradle整合 api 'com.tencent.tbs.tbssdk:sdk:43697',如果是在App裡整合可以把api換成implementation

2.AndroidStudio匯入騰訊X5

a.把下載好的jar包匯入libs,然後run as,再把jnilibs匯入main包下

b. module的build.gradle新增cpu適配

3.Application中騰訊X5初始化,在onCreate()方法呼叫init方法

QbSdk.initX5Environment(this,new QbSdk.PreInitCallback() {
   @Override
   public void onCoreInitFinished() {
 
   }
 
   @Override
   public void onViewInitFinished(boolean b) {
    Log.e("xxx","hasLoad"+b); 
   //此處將核心載入是否成功的狀態儲存到本地,SharePreference工具類可換為自己的
    SharedPreferenceUtils.saveBoolean(getApplicationContext(),"hasLoad",b);
   }
  });

4.應用內呼叫,無論是否載入核心,都是把線上的文件下載到本地然後開啟,不同的是,未載入核心會藉助QQ瀏覽器或其他App的檔案瀏覽功能類似微信(這個呼叫,騰訊X5已自動處理,我們無需關心),而載入核心後,使用X5的TbsReaderView來開啟檔案,接下來就是具體程式碼。

a.bulid.gradle中整合Retrofit,RxJava和進度管理器ProgressManager

 implementation 'io.reactivex:rxandroid:1.2.1'
 implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
 implementation 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
 implementation 'com.squareup.retrofit2:retrofit:2.3.0'
 implementation 'io.reactivex:rxjava:1.2.6'
 implementation 'me.jessyan:progressmanager:1.5.0'

寫網路下載工具

public interface LoadFileApi {
 @GET
 Call<ResponseBody> loadPdfFile(@Url String fileUrl);
}
public class LoadFileModel {
 //使用該方法來下載檔案
 public static void loadPdfFile(String url,Callback<ResponseBody> callback) {
  Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://www.baidu.com/")
    .client(ProgressManager.getInstance().with(new OkHttpClient.Builder())
      .build())
    .addConverterFactory(GsonConverterFactory.create())
    .build();
  LoadFileApi mLoadFileApi = retrofit.create(LoadFileApi.class);
  if (!TextUtils.isEmpty(url)) {
   Call<ResponseBody> call = mLoadFileApi.loadPdfFile(url);
   call.enqueue(callback);
  }
 }
}

b.具體呼叫

首先註冊檔案進度下載監聽

private ProgressDialog commonProgressDialog;//切換為自己的進度控制元件
 private ProgressInfo mLastDownloadingInfo;
 ProgressManager.getInstance().addResponseListener(url,new ProgressListener() {
            @Override
            public void onProgress(ProgressInfo progressInfo) {
             if (mLastDownloadingInfo == null) {
              mLastDownloadingInfo = progressInfo;
             }
             //因為是以請求開始時的時間作為 Id,所以值越大,說明該請求越新
             if (progressInfo.getId() < mLastDownloadingInfo.getId()) {
              return;
             } else if (progressInfo.getId() > mLastDownloadingInfo.getId()) {
              mLastDownloadingInfo = progressInfo;
             }
             int progress = mLastDownloadingInfo.getPercent();
             commonProgressDialog.setProgress(progress);
             Log.d("xxx","--Download-- " + progress + " % " + mLastDownloadingInfo.getSpeed() + " byte/s " + mLastDownloadingInfo.toString());
             if (mLastDownloadingInfo.isFinish()) {
              //說明已經下載完成
              commonProgressDialog.dismiss();
              Log.d("xxx","--Download-- finish");
             }
            }
            @Override
            public void onError(long id,Exception e) {
             e.printStackTrace();
             new Handler().post(new Runnable() {
              @Override
              public void run() {
                commonProgressDialog.dismiss();
              }
             });
            }
           });
          }

然後開啟檔案

private static final String DOWN_DIR = Environment.getExternalStorageDirectory()
   + File.separator+"Download"; //檔案下載的路徑,可以自定義
//開啟檔案
 private void openFile(String filePath,String fileName) {
  boolean hasLoad = SharedPreferenceUtils.getBoolean(mContext,"hasLoad");//是否記載核心
  if (hasLoad){
  //展示檔案的Activity
   Intent intentDoc = new Intent(this,FileDisplayActivity.class);
   intentDoc.putExtra("path",filePath);
   intentDoc.putExtra("fileName",fileName);
   startActivity(intentDoc);
  }else {
   if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
    Toast.makeText(this,"當前SD不可用",Toast.LENGTH_LONG).show();
    return;
   }
   try {
    File file = new File(DOWN_DIR,fileName);
    if (file.exists()){
     QbSdk.openFileReader(this,file.getAbsolutePath(),null,new ValueCallback<String>() {
      @Override
      public void onReceiveValue(String s) {
       Log.e("xxx",s);
      }
     });
    } else {
     downLoadFile(filePath,fileName);
    }
   } catch (Exception e) {
    e.printStackTrace();
    ToastUtils.showShortToast(mContext,"已下載過了");
   }
  }
 }
 private void downLoadFile(final String url,final String fileName) {
  commonProgressDialog.show();
  LoadFileModel.loadPdfFile(url,new Callback<ResponseBody>() {
   @Override
   public void onResponse(@NonNull Call<ResponseBody> call,@NonNull Response<ResponseBody> response) {
    InputStream is = null;
    byte[] buf = new byte[2048];
    int len;
    FileOutputStream fos = null;
    try {
     ResponseBody responseBody = response.body();
     if (responseBody != null) {
      is = responseBody.byteStream();
      final File file = new File(DOWN_DIR,fileName);
      fos = new FileOutputStream(file);
      while ((len = is.read(buf)) != -1) {
       fos.write(buf,len);
      }
      fos.flush();
      //未載入核心呼叫方法
      QbSdk.openFileReader(mContext,new ValueCallback<String>() {
       @Override
       public void onReceiveValue(String s) {
        Log.e("xxx",s);
       }
      });
      ToastUtils.showLongToast(MeetingDetailActivity.this,"下載成功,儲存在Download資料夾下");
     }
    } catch (Exception e) {
     commonProgressDialog.dismiss();
     ProgressManager.getInstance().notifyOnErorr(url,e);
     ToastUtils.showLongToast(MeetingDetailActivity.this,"下載失敗");
    } finally {
     try {
      if (is != null)
       is.close();
     } catch (IOException e) {
      e.printStackTrace();
     }
     try {
      if (fos != null)
       fos.close();
     } catch (IOException e) {
      e.printStackTrace();
     }
    }
   }
   @Override
   public void onFailure(@NonNull Call<ResponseBody> call,@NonNull Throwable t) {
    t.printStackTrace();
    ToastUtils.showShortToast(MeetingDetailActivity.this,"下載失敗");
    commonProgressDialog.dismiss();
   }
  });
 }

FileDisplayActivity程式碼,對於一些包名可以切換為自己的包名,還有一些第三方庫像進度展示,也可以切換為自己的進度控制元件

import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import com.anshi.oatencentschool.R;
import com.anshi.oatencentschool.utils.DialogBuild;
import com.anshi.oatencentschool.utils.StatusBarUtils;
import com.anshi.oatencentschool.utils.ToastUtils;
import com.anshi.oatencentschool.utils.WeakHandler;
import com.anshi.oatencentschool.utils.filetool.LoadFileModel;
import com.anshi.oatencentschool.utils.filetool.SuperFileView2;
import com.kaopiz.kprogresshud.KProgressHUD;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import me.jessyan.progressmanager.ProgressListener;
import me.jessyan.progressmanager.ProgressManager;
import me.jessyan.progressmanager.body.ProgressInfo;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class FileDisplayActivity extends AppCompatActivity {
 private String TAG = "FileDisplayActivity";
 //Tencent 提供的TBS閱讀瀏覽功能,不借助第三方軟體開啟office和pdf檔案
 private SuperFileView2 mSuperFileView;
 private String filePath;
 private TextView mTextView;
 private static final String DOWN_DIR = Environment.getExternalStorageDirectory()
   + File.separator+"Download";
 private String fileName;
 private KProgressHUD commonProgressDialog;
 private WeakHandler weakHandler = new WeakHandler(new Handler.Callback() {
  @Override
  public boolean handleMessage(Message msg) {
   int progress = msg.arg1;
   if (progress==100){
    commonProgressDialog.setProgress(progress);
    commonProgressDialog.dismiss();
   }else {
    commonProgressDialog.setProgress(progress);
   }
   return true;
  }
 });
 @Override
 protected void onCreate(@Nullable Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_file_display);
  getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON|WindowManager.LayoutParams.FLAG_FULLSCREEN);
  commonProgressDialog = DialogBuild.getBuild().createCommonProgressDialog(this,"下載中");
  init();
 }
 /**
  * 初始化
  */
 public void init() {
  mTextView = (TextView) findViewById(R.id.file_album_name);
  fileName = getIntent().getStringExtra("fileName");
  int lastIndexOf = fileName.lastIndexOf(".");
  String substring = fileName.substring(0,lastIndexOf);
  mTextView.setText(substring);
  mSuperFileView = (SuperFileView2) findViewById(R.id.mSuperFileView);
  mSuperFileView.setOnGetFilePathListener(new SuperFileView2.OnGetFilePathListener() {
   @Override
   public void onGetFilePath(SuperFileView2 mSuperFileView2) {
    getFilePathAndShowFile(mSuperFileView);
   }
  });
  Intent intent = this.getIntent();
  String path = (String) intent.getSerializableExtra("path");
  if (!TextUtils.isEmpty(path)) {
   Log.d(TAG,"檔案path:" + path);
   setFilePath(path);
  }
  mSuperFileView.show();
  ProgressManager.getInstance().addResponseListener(path,new ProgressListener() {
   @Override
   public void onProgress(ProgressInfo progressInfo) {
    int percent = progressInfo.getPercent();
    Message obtain = Message.obtain();
    obtain.arg1 = percent;
    weakHandler.sendMessage(obtain);
   }
   @Override
   public void onError(long id,Exception e) {
   }
  });
 }
 @Override
 protected void onResume() {
  super.onResume();
  StatusBarUtils.setWindowStatusBarColor(this,R.color.color_main);
 }
 /**
  * 顯示檔案
  * @param mSuperFileView2 控制元件
  */
 private void getFilePathAndShowFile(SuperFileView2 mSuperFileView2) {
  if (getFilePath().contains("http")&&!new File(DOWN_DIR,fileName).exists()) {//網路地址要先下載
   downLoadFile(getFilePath(),fileName,mSuperFileView2);
  } else {
   try {
    mSuperFileView2.displayFile(new File(DOWN_DIR,fileName));
   }catch (Exception e){
    e.printStackTrace();
   }
  }
 }
 public void setFilePath(String fileUrl) {
  this.filePath = fileUrl;
 }
 private String getFilePath() {
  return filePath;
 }
 /**
  * 回退上一級選單
  * @param view 控制元件
  */
 public void onClick(View view) {
  finish();
 }
 private void downLoadFile(final String url,final String fileName,final SuperFileView2 mSuperFileView2) {
  commonProgressDialog.show();
  LoadFileModel.loadPdfFile(url,@NonNull Response<ResponseBody> response) {
    InputStream is = null;
    byte[] buf = new byte[2048];
    int len;
    FileOutputStream fos = null;
    try {
     ResponseBody responseBody = response.body();
      is = responseBody.byteStream();
     final File file = new File(DOWN_DIR,fileName);
     fos = new FileOutputStream(file);
     while ((len = is.read(buf)) != -1) {
      fos.write(buf,len);
     }
     fos.flush();
     mSuperFileView2.displayFile(file);
     ToastUtils.showLongToast(FileDisplayActivity.this,儲存在Download資料夾下");
    } catch (Exception e) {
     commonProgressDialog.dismiss();
     ToastUtils.showLongToast(FileDisplayActivity.this,@NonNull Throwable t) {
    t.printStackTrace();
    ToastUtils.showShortToast(FileDisplayActivity.this,"下載失敗");
    commonProgressDialog.dismiss();
   }
  });
  }
}

佈局Layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/activity_file_display"
 android:layout_width="match_parent"
 android:fitsSystemWindows="true"
 android:layout_height="match_parent">
 <android.support.v7.widget.Toolbar
  android:layout_width="match_parent"
  android:layout_height="46dp"
  android:background="@color/color_main"
  android:id="@+id/file_toolbar"
  >
  <TextView
   android:layout_width="wrap_content"
   android:layout_height="match_parent"
   android:id="@+id/file_album_name"
   android:layout_gravity="center"
   android:gravity="center"
   android:maxLines="2"
   android:ellipsize="end"
   android:textSize="14sp"
   android:textColor="#FFF"
   />
 </android.support.v7.widget.Toolbar>
 <FrameLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_below="@id/file_toolbar"
  >
  <com.anshi.oatencentschool.utils.filetool.SuperFileView2
   android:id="@+id/mSuperFileView"
   android:layout_width="match_parent"
   android:layout_height="match_parent"/>
  <RelativeLayout
   android:layout_width="wrap_content"
   android:layout_gravity="center|start"
   android:layout_height="wrap_content">
   <RadioButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:button="@null"
    android:onClick="onClick"
    android:id="@+id/back_icon"
    android:drawableStart="@drawable/svg_left_back_blur"
    android:layout_marginStart="10dp"
    />
  </RelativeLayout>
  <!--<RadioButton-->
   <!--android:layout_width="wrap_content"-->
   <!--android:layout_height="wrap_content"-->
   <!--android:button="@null"-->
   <!--android:visibility="gone"-->
   <!--android:layout_gravity="end|bottom"-->
   <!--android:onClick="saveLocal"-->
   <!--android:layout_marginBottom="10dp"-->
   <!--android:layout_marginEnd="10dp"-->
   <!--android:drawableStart="@drawable/vector_drawable_down_load"-->
   <!--android:layout_marginStart="10dp"-->
   <!--/>-->
 </FrameLayout>
</RelativeLayout>

SuperFileView2程式碼,這個自定義的類是從https://github.com/ZhongXiaoHong/superFileView匯入

import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.tencent.smtt.sdk.TbsReaderView;
import java.io.File;
/**
 *
 * Created by 12457 on 2017/8/29.
 */
public class SuperFileView2 extends FrameLayout {
 private static String TAG = "SuperFileView";
 private TbsReaderView mTbsReaderView;
 private Context context;
 public SuperFileView2(Context context) {
  this(context,0);
 }
 public SuperFileView2(Context context,AttributeSet attrs) {
  this(context,attrs,AttributeSet attrs,int defStyleAttr) {
  super(context,defStyleAttr);
  mTbsReaderView = new TbsReaderView(context,new TbsReaderView.ReaderCallback() {
   @Override
   public void onCallBackAction(Integer integer,Object o,Object o1) {
   }
  });
  this.addView(mTbsReaderView,new LinearLayout.LayoutParams(-1,-1));
  this.context = context;
 }
 private OnGetFilePathListener mOnGetFilePathListener;
 public void setOnGetFilePathListener(OnGetFilePathListener mOnGetFilePathListener) {
  this.mOnGetFilePathListener = mOnGetFilePathListener;
 }
 private TbsReaderView getTbsReaderView(Context context) {
  return new TbsReaderView(context,Object o1) {
   }
  });
 }
 public void displayFile(File mFile) {
  if (mFile != null && !TextUtils.isEmpty(mFile.toString())) {
   //增加下面一句解決沒有TbsReaderTemp資料夾存在導致載入檔案失敗
   String bsReaderTemp = Environment.getExternalStorageDirectory()+ File.separator+"TbsReaderTemp";
   File bsReaderTempFile =new File(bsReaderTemp);
   if (!bsReaderTempFile.exists()) {
    Log.d("xxx","準備建立/storage/emulated/0/TbsReaderTemp!!");
    boolean mkdir = bsReaderTempFile.mkdir();
    if(!mkdir){
     Log.d("xxx","建立/storage/emulated/0/TbsReaderTemp失敗!!!!!");
    }
   }
   //載入檔案
   Bundle localBundle = new Bundle();
   Log.d("xxx",mFile.toString());
   localBundle.putString("filePath",mFile.toString());
   localBundle.putString("tempPath",bsReaderTemp);
   if (mTbsReaderView == null){
    mTbsReaderView = getTbsReaderView(context.getApplicationContext());
    String fileType = getFileType(mFile.toString());
    boolean bool = mTbsReaderView.preOpen(fileType,false);
    if (bool) {
     try {
      mTbsReaderView.openFile(localBundle);
     }catch (Exception e){
      e.printStackTrace();
     }
    }
   }else {
    String fileType = getFileType(mFile.toString());
    boolean bool = mTbsReaderView.preOpen(fileType,false);
    if (bool) {
     try {
      mTbsReaderView.openFile(localBundle);
     }catch (Exception e){
      e.printStackTrace();
     }
    }
   }
  } else {
   Log.d("xxx","檔案路徑無效!");
  }
 }
 /***
  * 獲取檔案型別
  *
  * @param paramString
  * @return
  */
 private String getFileType(String paramString) {
  String str = "";
  if (TextUtils.isEmpty(paramString)) {
   Log.d(TAG,"paramString---->null");
   return str;
  }
  Log.d(TAG,"paramString:" + paramString);
  int i = paramString.lastIndexOf('.');
  if (i <= -1) {
   Log.d(TAG,"i <= -1");
   return str;
  }
  str = paramString.substring(i + 1);
  Log.d(TAG,"paramString.substring(i + 1)------>" + str);
  return str;
 }
 public void show() {
  if(mOnGetFilePathListener!=null){
   mOnGetFilePathListener.onGetFilePath(this);
  }
 }
 /***
  * 將獲取File路徑的工作,“外包”出去
  */
 public interface OnGetFilePathListener {
  void onGetFilePath(SuperFileView2 mSuperFileView2);
 }
 public void onStopDisplay() {
  if (mTbsReaderView != null) {
   mTbsReaderView.onStop();
  }
 }
}

載入核心後開啟檔案

未載入核心開啟檔案

總結

以上所述是小編給大家介紹的Android整合騰訊X5實現文件瀏覽功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回覆大家的。在此也非常感謝大家對我們網站的支援!如果你覺得本文對你有幫助,歡迎轉載,煩請註明出處,謝謝!