最近在做结算功能,需要上传发票功能,发票有电子和图片发票两种,技术这边有两种方案,一种是上传图片文件,还有一种是上传PDF格式发票文件,但是结算时财务说图片文件上面没有公司盖章,是无效的,于是把方案改为电子发票PDF和纸质发票,刚开始使用的文件管理器搜索手机内的PDF文件,在4.4系统上面打开文件管理器可以过滤掉非.pdf格式文件,在6.0及以上系统没有过滤掉,用的是intent打开url的方式打开文件管理器,在返回的结果中根据URL转化为文件,然后上传。

1.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格式文件

2.通过ContentProvider搜索pdf格式文件核心代码如下:

/**
 * 获取手机文档数据
 *
 * @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();
}

3.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;
    }

}

4.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>

5.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);

        }
    }
}

6.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);
    }
}

7.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>

8.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>

9.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>

10.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" />

11.在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.");
                }

            }
        });
    }
}

12.实现的完整效果图如下:

Android实现搜索手机内的PDF文件

13.后面会给出源码地址,利用腾讯x5浏览器内核实现PDF预览

 

 

相关文章:

  • 2022-12-23
  • 2021-05-25
  • 2021-12-03
  • 2021-12-29
  • 2021-07-26
  • 2021-10-20
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-07-10
  • 2021-09-16
  • 2021-05-20
  • 2022-01-29
  • 2021-10-27
相关资源
相似解决方案