前言:
最近在做订单结算功能,需要上传发票,发票有电子和图片发票两种,技术这边有两种方案,一种是上传图片文件,还有一种是上传PDF格式发票文件,但是结算时财务说图片文件上面没有公司盖章,是无效的,于是把方案改为电子发票PDF和纸质发票,刚开始使用的文件管理器搜索手机内的PDF文件,在4.4系统上面打开文件管理器可以过滤掉非.pdf格式文件,在6.0及以上系统没有过滤掉,用的是intent打开url的方式打开文件管理器,在返回的结果中根据URL转化为文件,然后上传。
1.先上效果图,无图无真相,图能说明一切:
2.Intent方式打开pdf格式文件:
代码语言:javascript复制 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));
}
Jetbrains全家桶1年46,售后保障稳定
这种方式也可以拿到.pdf格式的文件,但是在小米手机上有个最近文件记录打开时返回报错,由于时间和项目着急上线,所以没有适配6.0及以上系统的手机,采用了第2种方式—-通过ContentProvider搜索手机内的.pdf格式文件
3.通过ContentProvider搜索pdf格式文件核心代码如下:
博主中搜索的是.pdf格式的文件,如果想搜索其他格式文件方法类似,改后缀名比如.txt,.doc,.png等等,小伙伴们可以自行尝试下,看看效果如何,这里就不一一尝试和介绍了.
代码语言:javascript复制/**
* 获取手机文档数据
*
* @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代码:
代码语言:javascript复制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代码:
代码语言:javascript复制<?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代码:
代码语言:javascript复制/**
* @作者: 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
代码语言:javascript复制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代码
代码语言:javascript复制<?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
代码语言:javascript复制<?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
代码语言:javascript复制<?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加上权限申请
代码语言:javascript复制<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动态申请权限
代码语言:javascript复制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文件搜索
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/234928.html原文链接:https://javaforall.cn