700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Android实现PDF格式文件预览

Android实现PDF格式文件预览

时间:2023-07-20 05:40:59

相关推荐

Android实现PDF格式文件预览

前言:

接着上一篇的博客,在搜索出手机内的.pdf格式文件后,实现pdf文件的预览的方式有很多,

1.Android PdfViewer项目地址:

/barteksc/AndroidPdfViewer 功能很强大, 使用也比较广, 亲测可以使用. 唯一的缺点 :添加到项目中 会使apk增加10M左右, 这是最不能接受的, 故弃用.

2.PdfViewPager:

项目地址: /voghDev/PdfViewPager 可加载assets/SD卡/URL(在线预览) , 优点: 使用比较方便, 也不大

3.mozilla开源的PDF.js

项目地址:GitHub - mozilla/pdf.js: PDF Reader in JavaScript

是将pdf.js和相关的文件全部下载下来并拷贝的工程中的assets目录,apk会增加4M左右

4.腾讯的tbs

项目地址:腾讯浏览服务

这种方式是实现本地预览,把pdf文件下载到本地或直接加载本地的pdf文件

优点:使用方便,集成简单,包不大,可以远程依赖(ps:本文采用的是这种方式)

缺点:不能很好地支持部分64手机,Androidx兼容也不是很好.

5.实现的效果图如下:

6.跳转事件代码

//跳转到文件预览pdfAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {@Overridepublic void onItemClick(BaseQuickAdapter adapter, View view, int position) {String fileUrl = Objects.requireNonNull(pdfAdapter.getItem(position)).getFilePath();String fileName = Objects.requireNonNull(pdfAdapter.getItem(position)).getFileName();PDFPreViewActivity.actionStart(PDFSearchActivity.this, fileUrl, fileName);}});

7.PDFPreViewActivity代码:

/*** @作者: njb* @时间: /9/11 20:31* @描述: pdf文件预览*/public class PDFPreViewActivity extends AppCompatActivity implements TbsReaderView.ReaderCallback {private TbsReaderView mTbsReaderView;private String mFileName;private TextView tv_download;private long mRequestId;private DownloadObserver mDownloadObserver;private ProgressBar progressBar_download;private DownloadManager mDownloadManager;private String fileName;private String fileUrl;private String TAG = PDFPreViewActivity.class.getSimpleName();private RelativeLayout rootRl;private TextView tv_title;private ImageView iv_back;​@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_pdf_preview);initIntent();initTbsReaderView();mTbsReaderView = new TbsReaderView(this, this);rootRl.addView(mTbsReaderView, new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));if ((fileUrl == null) || (fileUrl.length() <= 0)) {Toast.makeText(PDFPreViewActivity.this, "获取文件url出错了", Toast.LENGTH_SHORT).show();return;}mFileName = PDFUtil.parseName(fileUrl);requestPermission();​isDown();}​private void initIntent() {if (getIntent() != null && getIntent().getExtras() != null) {fileUrl = getIntent().getExtras().getString("fileUrl");fileName = getIntent().getExtras().getString("fileName");}}​//初始化TbsReaderView 5-3private void initTbsReaderView() {rootRl = findViewById(R.id.rl_tbsView);tv_download = findViewById(R.id.tv_download);progressBar_download = findViewById(R.id.progressBar_download);tv_title = findViewById(R.id.tv_title);tv_title.setText("PDF文件预览");iv_back = findViewById(R.id.iv_back);iv_back.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {finish();}});}​​private void requestPermission() {RxPermissions rxPermissions = new RxPermissions(this);​if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {rxPermissions.requestEach(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE).subscribe(new Consumer<Permission>() {@Overridepublic void accept(Permission permission) {if (permission.granted) {// 用户已经同意该权限​​Log.d(TAG, permission.name + " is granted.");} else if (permission.shouldShowRequestPermissionRationale) {// 用户拒绝了该权限,没有选中『不再询问』(Never ask again),那么下次再次启动时,还会提示请求权限的对话框Log.d(TAG, permission.name + " is denied. More info should be provided.");} else {// 用户拒绝了该权限,并且选中『不再询问』Log.d(TAG, permission.name + " is denied.");}​}});}}​private void isDown() {if (isLocalExist() || fileUrl.contains("storage")) {tv_download.setText("打开文件");tv_download.setVisibility(View.GONE);displayFile();} else {if (!fileUrl.contains("http")) {new AlertDialog.Builder(PDFPreViewActivity.this).setTitle("温馨提示:").setMessage("文件的url地址不合法哟,无法进行下载").setCancelable(false).setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {return;}}).create().show();}startDownload();}}​​@TargetApi(Build.VERSION_CODES.GINGERBREAD)private void queryDownloadStatus() {DownloadManager.Query query = new DownloadManager.Query().setFilterById(mRequestId);Cursor cursor = null;try {cursor = mDownloadManager.query(query);if (cursor != null && cursor.moveToFirst()) {// 已经下载的字节数long currentBytes = cursor.getLong(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));// 总需下载的字节数long totalBytes = cursor.getLong(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));// 状态所在的列索引int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));tv_download.setText("下载中...(" + PDFUtil.FormetFileSize(currentBytes)+ "/" + PDFUtil.FormetFileSize(totalBytes) + ")");// 将当前下载的字节数转化为进度位置int progress = (int) ((currentBytes * 1.0) / totalBytes * 100);progressBar_download.setProgress(progress);​Log.i("downloadUpdate: ", currentBytes + " " + totalBytes + " "+ status + " " + progress);if (DownloadManager.STATUS_SUCCESSFUL == status&& tv_download.getVisibility() == View.VISIBLE) {tv_download.setVisibility(View.GONE);tv_download.performClick();if (isLocalExist()) {tv_download.setVisibility(View.GONE);progressBar_download.setVisibility(View.GONE);displayFile();}}}} finally {if (cursor != null) {cursor.close();}}}​/*** 加载显示文件内容*/private void displayFile() {Bundle bundle = new Bundle();if (isLocalExist()) {bundle.putString("filePath", getLocalFile().getPath());}if (fileUrl.contains("storage")) {bundle.putString("filePath", fileUrl);}​bundle.putString("tempPath", Environment.getExternalStorageDirectory().getPath());boolean result = mTbsReaderView.preOpen(PDFUtil.getFileType(mFileName), false);if (result) {mTbsReaderView.openFile(bundle);} else {​File file = new File(getLocalFile().getPath());if (file.exists()) {Intent openintent = new Intent();openintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);String type = PDFUtil.getMIMEType(file);// 设置intent的data和Type属性。openintent.setDataAndType(Uri.fromFile(file), type);// 跳转startActivity(openintent);finish();}}}​/*** 下载文件*/@SuppressLint("NewApi")private void startDownload() {mDownloadObserver = new DownloadObserver(new Handler());getContentResolver().registerContentObserver(Uri.parse("content://downloads/my_downloads"), true,mDownloadObserver);​mDownloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);//将含有中文的url进行encodeString mFileUrl = toUtf8String(fileUrl);try {DownloadManager.Request request = new DownloadManager.Request(Uri.parse(mFileUrl));request.setDestinationInExternalPublicDir(Constants.DOWNLOAD_PDF_PATH, mFileName);request.allowScanningByMediaScanner();request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);mRequestId = mDownloadManager.enqueue(request);​} catch (Exception e) {e.printStackTrace();}}​/*** 跳转页面** @param context* @param fileUrl 文件url* @param fileName 文件名*/public static void actionStart(Context context, String fileUrl, String fileName) {Intent intent = new Intent(context, PDFPreViewActivity.class);intent.putExtra("fileUrl", fileUrl);intent.putExtra("fileName", fileName);context.startActivity(intent);}​​/*** 是否为本地文件** @return*/private boolean isLocalExist() {return getLocalFile().exists();}​/*** 本地文件目录** @return*/private File getLocalFile() {return new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), mFileName);}​@Overridepublic void onCallBackAction(Integer integer, Object o, Object o1) {​}​​private class DownloadObserver extends ContentObserver {​private DownloadObserver(Handler handler) {super(handler);}​@Overridepublic void onChange(boolean selfChange, Uri uri) {queryDownloadStatus();}}​​@Overrideprotected void onDestroy() {super.onDestroy();mTbsReaderView.onStop();if (mDownloadObserver != null) {getContentResolver().unregisterContentObserver(mDownloadObserver);}}}

8.activity_pdf_preview.xml布局代码

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#f5f5f5"android:orientation="vertical">​<include layout="@layout/toolbar" />​<RelativeLayoutandroid:id="@+id/rl_tbsView"android:layout_width="match_parent"android:layout_height="match_parent">​<TextViewandroid:id="@+id/tv_download"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="开始下载"android:textColor="@android:color/black"android:textSize="13sp" />​<ProgressBarandroid:id="@+id/progressBar_download"style="?android:attr/progressBarStyleHorizontal"android:layout_width="match_parent"android:layout_height="3dp"android:layout_below="@+id/tv_download"android:layout_marginLeft="12dp"android:layout_marginRight="12dp"android:layout_marginTop="6dp"android:max="100"android:progressDrawable="@drawable/progressbar_color" /></RelativeLayout>​</LinearLayout>

9.build.gradle配置

implementation fileTree(include: ['*.jar'], dir: 'libs')implementation 'androidx.appcompat:appcompat:1.1.0'implementation 'androidx.constraintlayout:constraintlayout:1.1.3'testImplementation 'junit:junit:4.12'androidTestImplementation 'androidx.test:runner:1.2.0'androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'//Rx权限implementation 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.5@aar'implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.40'implementation 'androidx.recyclerview:recyclerview:1.0.0'implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'implementation 'io.reactivex.rxjava2:rxjava:2.2.3'implementation "com.tencent.tbs.tbssdk:sdk:43697"

10.Manifest权限配置

<uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_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.MOUNT_UNMOUNT_FILESYSTEMS" /><!-- 硬件加速对X5视频播放非常重要,建议开启 --><uses-permission android:name="android.permission.GET_TASKS" />​<uses-permission android:name="android.permission.VIBRATE" /><uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" /><uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER" />

11.遇到的问题:

11.1 64位手机so加载失败,由于腾讯x5浏览器官方的sdk库文件就提供了一种类型的so库,所以在APP的build.gradle目录下配置支持其他手机类型,配置如下:

ndk {abiFilters "armeabi", "armeabi-v7a", "x86", "mips"}

如果不指定so的目录,默认就会默认匹配main下的jniLibs目录:

11.2 x5浏览器初始化成功,但是加载失败,有些手机不兼容,解决方法如下:

使用远程依赖的方式加载 ,目前Androidx加载第一次可能会失败,多加载几次就好了.

12.最后,项目的源码下载地址为:

PDFSearch: Android实现手机内PDF文件搜索

13.csdn下载地址:没有积分的同学可以去码云下载.

PDFSearch.zip-Android文档类资源-CSDN下载

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。