大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全家桶1年46,售后保障稳定
前言:
最近在做订单结算功能,需要上传发票,发票有电子和图片发票两种,技术这边有两种方案,一种是上传图片文件,还有一种是上传PDF格式发票文件,但是结算时财务说图片文件上面没有公司盖章,是无效的,于是把方案改为电子发票PDF和纸质发票,刚开始使用的文件管理器搜索手机内的PDF文件,在4.4系统上面打开文件管理器可以过滤掉非.pdf格式文件,在6.0及以上系统没有过滤掉,用的是intent打开url的方式打开文件管理器,在返回的结果中根据URL转化为文件,然后上传。
1.先上效果图,无图无真相,图能说明一切:
2.Intent方式打开pdf格式文件:
Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("application/pdf"); try { startActivityForResult(intent, REQUEST_CODE); } catch (ActivityNotFoundException e) { //alert user that file manager not working ToastUtils.ToastShort(Utils.getContext().getResources().getString(R.string.toast_pick_file_error)); }
这种方式也可以拿到.pdf格式的文件,但是在小米手机上有个最近文件记录打开时返回报错,由于时间和项目着急上线,所以没有适配6.0及以上系统的手机,采用了第2种方式—-通过ContentProvider搜索手机内的.pdf格式文件
3.通过ContentProvider搜索pdf格式文件核心代码如下:
博主中搜索的是.pdf格式的文件,如果想搜索其他格式文件方法类似,改后缀名比如.txt,.doc,.png等等,小伙伴们可以自行尝试下,看看效果如何,这里就不一一尝试和介绍了.
/** * 获取手机文档数据 * * @param */ public void getDocumentData() { String[] columns = new String[]{MediaStore.Files.FileColumns._ID, MediaStore.Files.FileColumns.MIME_TYPE, MediaStore.Files.FileColumns.SIZE, MediaStore.Files.FileColumns.DATE_MODIFIED, MediaStore.Files.FileColumns.DATA}; String select = "(_data LIKE '%.pdf')"; ContentResolver contentResolver = getContentResolver(); Cursor cursor = contentResolver.query(MediaStore.Files.getContentUri("external"), columns, select, null, null); int columnIndexOrThrow_DATA = 0; if (cursor != null) { columnIndexOrThrow_DATA = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA); } if (cursor != null) { while (cursor.moveToNext()) { String path = cursor.getString(columnIndexOrThrow_DATA); PDFFileInfo document = PDFUtil.getFileInfoFromFile(new File(path)); pdfData.add(document); Log.d(TAG, " pdf " + document); } } cursor.close(); }
4.PDFSearchActivity代码:
public class PDFSearchActivity extends AppCompatActivity { private RecyclerView mRecyclerView; private ProgressDialog progressDialog; private PDFAdapter pdfAdapter; private ImageView imgBack; private TextView tvTitle; private TextView tvFinish; private ArrayList<PDFFileInfo> pdfData = new ArrayList<>(); private String TAG = PDFSearchActivity.class.getSimpleName(); @SuppressLint("HandlerLeak") private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == 1) { initRecyclerView(); } } }; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_pdf_select); initViews(); initListener(); } private void initViews() { mRecyclerView = findViewById(R.id.rv_pdf); imgBack = findViewById(R.id.iv_back); tvTitle = findViewById(R.id.tv_title); tvFinish = findViewById(R.id.tv_right); tvTitle.setText("PDF文件搜索"); imgBack.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); showDialog(); new Thread() { @Override public void run() { super.run(); getFolderData(); } }.start(); } private void initListener() { } private void showDialog() { progressDialog = new ProgressDialog(this, ProgressDialog.THEME_HOLO_LIGHT); progressDialog.setMessage("正在加载数据中..."); progressDialog.setCanceledOnTouchOutside(false); progressDialog.show(); } private void initRecyclerView() { pdfAdapter = new PDFAdapter(this); View notDataView = getLayoutInflater().inflate(R.layout.pdf_empty_view, (ViewGroup) mRecyclerView.getParent(), false); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); mRecyclerView.setAdapter(pdfAdapter); pdfAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() { @Override public void onItemClick(BaseQuickAdapter adapter, View view, int position) { if (!pdfData.get(position).isSelect()) { if (getSelectNumber() >= 3) { Toast.makeText(PDFSearchActivity.this, "最多可选择3个文件", Toast.LENGTH_SHORT).show(); return; } } for (int i = 0; i < pdfData.size(); i++) { if (i == position) { if (pdfData.get(i).isSelect()) { pdfData.get(i).setSelect(false); } else { pdfData.get(i).setSelect(true); } } } adapter.notifyDataSetChanged(); tvFinish.setText("完成(" + getSelectNumber() + ")"); } }); if (pdfData != null && pdfData.size() > 0) { for (int i = 0; i < pdfData.size(); i++) { pdfData.get(i).setSelect(false); } pdfAdapter.setNewData(pdfData); } else { pdfAdapter.setEmptyView(notDataView); } progressDialog.dismiss(); } /** * 遍历文件夹中资源 */ public void getFolderData() { getDocumentData(); handler.sendEmptyMessage(1); } /** * 获取手机文档数据 * * @param */ public void getDocumentData() { String[] columns = new String[]{MediaStore.Files.FileColumns._ID, MediaStore.Files.FileColumns.MIME_TYPE, MediaStore.Files.FileColumns.SIZE, MediaStore.Files.FileColumns.DATE_MODIFIED, MediaStore.Files.FileColumns.DATA}; String select = "(_data LIKE '%.pdf')"; ContentResolver contentResolver = getContentResolver(); Cursor cursor = contentResolver.query(MediaStore.Files.getContentUri("external"), columns, select, null, null); int columnIndexOrThrow_DATA = 0; if (cursor != null) { columnIndexOrThrow_DATA = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA); } if (cursor != null) { while (cursor.moveToNext()) { String path = cursor.getString(columnIndexOrThrow_DATA); PDFFileInfo document = PDFUtil.getFileInfoFromFile(new File(path)); pdfData.add(document); Log.d(TAG, " pdf " + document); } } cursor.close(); } private int getSelectNumber() { int k = 0; for (int i = 0; i < pdfData.size(); i++) { if (pdfData.get(i).isSelect()) { k++; } } return k; } }
5.activity_pdf_select.xml代码:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <include layout="@layout/toolbar"/> <androidx.recyclerview.widget.RecyclerView android:id="@+id/rv_pdf" android:layout_width="match_parent" android:layout_height="match_parent"> </androidx.recyclerview.widget.RecyclerView> </LinearLayout>
6.PDFAdapter代码:
/** * @作者: njb * @时间: 2019/9/11 20:31 * @描述: pdf文件适配器类 */ public class PDFAdapter extends BaseQuickAdapter<PDFFileInfo, BaseViewHolder> { public PDFAdapter(@Nullable List<PDFFileInfo> data) { super(R.layout.item_pdf,data); } @Override protected void convert(BaseViewHolder helper, PDFFileInfo item) { if(item == null){ return; } helper.setText(R.id.tv_name , item.getFileName()); helper.setText(R.id.tv_size , PDFUtil.FormetFileSize(item.getFileSize())); helper.setText(R.id.tv_time , item.getTime()); if (item.isSelect()){ helper.getView(R.id.img_select).setBackgroundResource(R.mipmap.reward_selection_ok); }else { helper.getView(R.id.img_select).setBackgroundResource(R.mipmap.reward_selection_no); } } }
7.PDFUtil
public class PDFUtil { /** * 读取文件的最后修改时间的方法 */ public static String getFileLastModifiedTime(File f) { Calendar cal = Calendar.getInstance(); long time = f.lastModified(); SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); cal.setTimeInMillis(time); return formatter.format(cal.getTime()); } public static PDFFileInfo getFileInfoFromFile(File file) { PDFFileInfo fileInfo = new PDFFileInfo(); fileInfo.setFileName(file.getName()); fileInfo.setFilePath(file.getPath()); fileInfo.setFileSize(file.length()); // fileInfo.setDirectory(file.isDirectory()); fileInfo.setTime(PDFUtil.getFileLastModifiedTime(file)); int lastDotIndex = file.getName().lastIndexOf("."); if (lastDotIndex > 0) { String fileSuffix = file.getName().substring(lastDotIndex + 1); // fileInfo.setSuffix(fileSuffix); } return fileInfo; } public static String FormetFileSize(long fileS) { DecimalFormat df = new DecimalFormat("#.00"); String fileSizeString = ""; String wrongSize = "0B"; if (fileS == 0) { return wrongSize; } if (fileS < 1024) { fileSizeString = df.format((double) fileS) + "B"; } else if (fileS < 1048576) { fileSizeString = df.format((double) fileS / 1024) + "KB"; } else if (fileS < 1073741824) { fileSizeString = df.format((double) fileS / 1048576) + "MB"; } else { fileSizeString = df.format((double) fileS / 1073741824) + "GB"; } return fileSizeString; } /** * 利用文件url转换出文件名 * * @param url * @return */ public static String parseName(String url) { String fileName = null; try { fileName = url.substring(url.lastIndexOf("/") + 1); } finally { if (TextUtils.isEmpty(fileName)) { fileName = String.valueOf(System.currentTimeMillis()); } } return fileName; } /** * 将url进行encode,解决部分手机无法下载含有中文url的文件的问题(如OPPO R9) * * @param url * @return * @author xch */ public static String toUtf8String(String url) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < url.length(); i++) { char c = url.charAt(i); if (c >= 0 && c <= 255) { sb.append(c); } else { byte[] b; try { b = String.valueOf(c).getBytes("utf-8"); } catch (Exception ex) { System.out.println(ex); b = new byte[0]; } for (int j = 0; j < b.length; j++) { int k = b[j]; if (k < 0) k += 256; sb.append("%" + Integer.toHexString(k).toUpperCase()); } } } return sb.toString(); } public static String parseFormat(String fileName) { return fileName.substring(fileName.lastIndexOf(".") + 1); } }
8.PDFAdapter的Item代码
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_margin="@dimen/space_10"> <ImageView android:id="@+id/img" android:layout_width="60dp" android:layout_height="60dp" android:src="@mipmap/pdf" /> <ImageView android:id="@+id/img_select" android:layout_width="25dp" android:layout_height="25dp" android:background="@mipmap/reward_selection_no" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/tv_name" android:layout_width="0dp" android:layout_height="wrap_content" android:ellipsize="end" android:maxLines="1" android:text="深入浅出nodejs.pdf" android:layout_marginLeft="6dp" android:layout_marginRight="6dp" app:layout_constraintLeft_toRightOf="@+id/img" app:layout_constraintRight_toLeftOf="@+id/img_select"/> <TextView android:id="@+id/tv_size" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="2dp" android:text="KB" android:textSize="@dimen/text_size_11" app:layout_constraintTop_toBottomOf="@+id/tv_name" app:layout_constraintLeft_toRightOf="@+id/img" android:layout_marginLeft="6dp"/> <TextView android:id="@+id/tv_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="6dp" android:text="2019-09-21" android:textSize="@dimen/text_size_11" app:layout_constraintLeft_toRightOf="@+id/img" app:layout_constraintBottom_toBottomOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout>
9.pdf_search_shape.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@color/colorPrimary"/> <corners android:radius="@dimen/space_10"/> </shape>
10.pdf_empty_view.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:gravity="center" android:background="@color/white" android:orientation="vertical" android:layout_height="match_parent"> <ImageView android:layout_gravity="center" android:id="@+id/iv_nodata" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/no_date_without_text" android:visibility="visible" /> <TextView android:id="@+id/tvTip" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/str_blank" /> </LinearLayout>
11.Manifast加上权限申请
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" /> <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
12.在MainActivity动态申请权限
public class MainActivity extends AppCompatActivity { private static final String TAG = "RxPermissionTest"; private Button btnUpload; private ImageView ivBack; private TextView tvTitle; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViews(); requestPermission(); } private void initViews() { btnUpload = findViewById(R.id.tv_upload); ivBack = findViewById(R.id.iv_back); tvTitle = findViewById(R.id.tv_title); tvTitle.setText("PDFSearch"); ivBack.setVisibility(View.GONE); btnUpload.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(MainActivity.this, PDFSearchActivity.class)); } }); } @SuppressLint("InlinedApi") private void requestPermission() { RxPermissions rxPermissions = new RxPermissions(this); rxPermissions.requestEach(Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE) .subscribe(new Consumer<Permission>() { @Override public 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."); } } }); } }
13.后面会给出源码地址,实现PDF预览功能.欢迎小伙伴们留言,有问题提出,及时改进.
csdn下载地址:PDFSearch.zip-Android文档类资源-CSDN下载,由于现在csdn默认的下载都要积分,不能修改,所以很抱歉哈~~
14.没有积分的同学也可以去码云下载源码,地址为:
PDFSearch: Android实现手机内PDF文件搜索
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/234928.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...