有些App需要打开本地文件,这个功能怎么做呢,有些人自己封装了一套方法(佩服佩服),我搜来搜去最简单的方法是调用Android本身的文件管理系统。实现之后在这里记录一下,只需要三四步:

(以下代码主要来自于Android官方的Sample:Strorage Client)

1、在MainActivity类中加入以下方法:

private static final int READ_REQUEST_CODE = 1337;//自己指定一个intent的请求码,下面用到时解释。
    Uri filePathUri=null; //下面用于存放回传的文件地址。

//此方法用于调用系统的文件管理应用,选择文件并将路径传给本Activity
    public void performFileSearch() {

        // BEGIN_INCLUDE (use_open_document_intent)
        // ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's file browser.
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);//新建intent对象,参数为调用系统的文件管理系统。

        // Filter to only show results that can be "opened", such as a file (as opposed to a list
        // of contacts or timezones)
        intent.addCategory(Intent.CATEGORY_OPENABLE);

        // Filter to show only images, using the image MIME data type.
        // If one wanted to search for ogg vorbis files, the type would be "audio/ogg".
        // To search for all documents available via installed storage providers, it would be
        // 这里可以设置要显示的文件的类型,用MIME data tpe的规范来设置,常见的类型可以看这个网页:
        //https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
        //设置为*/*表示可打开所有文件。只显示pdf的话可以设置为application/pdf
        intent.setType("*/*");
        //要设置多种类型可打开,则需要用putExtra。
        intent.putExtra(Intent.EXTRA_MIME_TYPES,new String[]{"application/pdf","text/plain","application/vnd.openxmlformats-officedocument.wordprocessingml.document"});

        //这个方法将上面设置好的intent发出,调用android系统的文件管理系统,在用户选择点击文件之后将结果返回给本Activity。
        //READ_REQUEST_CODE为自己指定的一个任意整数,用于标记这个请求,以便下面收到回复的时候进行对比判断并作出相应的处理。
        //因为你的程序可能会发出多个intent和多个activity进行互动,每次互动就要有一个唯一的请求码进行标识。
        startActivityForResult(intent, READ_REQUEST_CODE);
    }

 

2、重写onActivityResult方法,接收用户点击选择文件的动作结果并进行处理:

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
        super.onActivityResult(requestCode, resultCode, resultData);
        if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {//用请求码过滤一下我们所需要的互动请求,并验证操作是否成功。
            // 用户所点选的文件将以URI地址方式回传,要对这个URI地址进行处理。
            // A URI to the document selected by the user document will be contained in the return intent
            // provided to this method as a parameter.  Pull that uri using "resultData.getData()"
            if (resultData != null) {
                filePathUri=resultData.getData();//获取回传的文件URI地址。以下两行代码是对所获取到的pdf进行处理并用RecyclerView显示到界面上,具体可以看前两篇blog的介绍。
                PdfViewAdapter pdfViewAdapter=new PdfViewAdapter(openPdf(filePathUri));//openPdf方法将pdf文件全部转化为bmp放入数组传给我们之前写好的Adapter
                recyclerView.setAdapter(pdfViewAdapter);//rv设置adapter
            }
        }
    }

3、重写MainActivity的onClick方法:(这里也就是调用上面第一步所写的方法而已,没什么特别)。

@Override
public void onClick(View v) {
    switch(v.getId()){
        case R.id.open:
            performFileSearch();//点击打开按钮的时候调用此方法调用系统的文件管理应用
            break;
    }
}

4、在界面XML文件中按钮的代码中指明使用上面的onClick方法:

<Button
    android:id="@+id/open"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="16dp"
    android:onClick="onClick"
    android:text="打开"
    app:layout_constraintEnd_toEndOf="parent"
    tools:layout_editor_absoluteY="3dp" />

记得要在Manifes文件中添加存储的读写权限:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="knowing.pleasure">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>

    <application
        android:allowBackup="true"
        android:requestLegacyExternalStorage="true"
        android:icon="@mipmap/ic_launcher"
……………………

并在打开app的时候检查权限,如用户没有授权则提醒用户授权。在onCreate方法中添加以下代码:

//申请sd读写权限
int permission_write = ContextCompat.checkSelfPermission(MainActivity.this,
        Manifest.permission.WRITE_EXTERNAL_STORAGE);
int permission_read = ContextCompat.checkSelfPermission(MainActivity.this,
        Manifest.permission.READ_EXTERNAL_STORAGE);
if (permission_write != PackageManager.PERMISSION_GRANTED
        || permission_read != PackageManager.PERMISSION_GRANTED) {
    Toast.makeText(this, "正在请求权限", Toast.LENGTH_SHORT).show();
    //申请权限,特征码自定义为1,可在回调时进行相关判断
    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
}

5、打开目录的方法(还没试验,先记录一下):

https://developer.android.com/training/data-storage/shared/documents-files?hl=zh-cn 以下代码段展示了如何创建和调用用于打开目录的 intent:


public void openDirectory(Uri uriToLoad) {
    // Choose a directory using the system's file picker.
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);

    // Provide read access to files and sub-directories in the user-selected
    // directory.
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

    // Optionally, specify a URI for the directory that should be opened in
    // the system file picker when it loads.
    intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, uriToLoad);

    startActivityForResult(intent, your-request-code);
}