软件编程
位置:首页>> 软件编程>> Android编程>> Android集成腾讯X5实现文档浏览功能

Android集成腾讯X5实现文档浏览功能

作者:hardWork_yulu  发布时间:2023-10-03 23:44:06 

标签:android,文档浏览

Android内部没有控件来直接显示文档,跳转WPS或其他第三方文档App体验性不好,使用腾讯X5内核能很好的解决的这一问题。

一、下载腾讯X5内核

1.前往https://x5.tencent.com/下载Android的内核,新版本的腾讯X5可以直接在bulid.gradle集成 api 'com.tencent.tbs.tbssdk:sdk:43697',如果是在App里集成可以把api换成implementation

Android集成腾讯X5实现文档浏览功能

2.AndroidStudio导入腾讯X5

a.把下载好的jar包导入libs,然后run as,再把jnilibs导入main包下

Android集成腾讯X5实现文档浏览功能

b. module的build.gradle添加cpu适配

Android集成腾讯X5实现文档浏览功能

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, 0, len);
     }
     fos.flush();
     //未加载内核调用方法
     QbSdk.openFileReader(mContext, file.getAbsolutePath(), null, 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, 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();
     is = responseBody.byteStream();
    final File file = new File(DOWN_DIR, fileName);
    fos = new FileOutputStream(file);
    while ((len = is.read(buf)) != -1) {
     fos.write(buf, 0, len);
    }
    fos.flush();
    mSuperFileView2.displayFile(file);
    ToastUtils.showLongToast(FileDisplayActivity.this, "下载成功,保存在Download文件夹下");
   } catch (Exception e) {
    commonProgressDialog.dismiss();
    ToastUtils.showLongToast(FileDisplayActivity.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(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, null, 0);
}
public SuperFileView2(Context context, AttributeSet attrs) {
 this(context, attrs, 0);
}
public SuperFileView2(Context context, AttributeSet attrs, int defStyleAttr) {
 super(context, attrs, 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, new TbsReaderView.ReaderCallback() {
  @Override
  public void onCallBackAction(Integer integer, Object o, 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实现文档浏览功能

未加载内核打开文件

Android集成腾讯X5实现文档浏览功能

总结

以上所述是小编给大家介绍的Android集成腾讯X5实现文档浏览功能,希望对大家有所帮助

来源:https://blog.csdn.net/hardWork_yulu/article/details/102636818

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com