将图像从Android上传到Amazon S3?

时间:2011-09-05 15:35:35

标签: android amazon-s3 amazon-web-services

我需要将位图上传到Amazon S3。我从未使用过S3,而且文档证明不太有用,因为我看不到任何内容来涵盖这个特定的要求。不幸的是,我很难花时间在这个项目上花一整天的时间来学习它们如何挂在一起,所以希望你们中的一个人能给我一些指示。

您是否可以指向我的参考资料来解释如何将文件推送到S3,并获得URL参考作为回报?

更具体地说: - 使用S3 Android SDK时凭据在哪里? - 我是否需要在上传文件之前创建一个存储桶,还是存在于存储桶之外? - 我使用哪种SDK方法将位图推送到S3? - 我是否正确地认为我需要CORE和S3库来做我需要的,而没有其他人?

7 个答案:

答案 0 :(得分:8)

查看Amazon S3 API documentation,了解使用Amazon S3可以做什么和不能做什么。请注意,有两个API,一个更简单的REST API和一个更复杂的SOAP API。

您可以编写自己的代码以使HTTP请求与REST API交互,或使用SOAP库来使用SOAP API。所有的Amazon服务都有这些标准的API端点(REST,SOAP),理论上你可以用任何编程语言编写客户端!

幸运的是,对于Android开发者来说,亚马逊已经发布了a (Beta) SDK,它可以帮助您完成所有这些工作。还有Getting Started指南和Javadocs。使用此SDK,您应该能够在几个小时内将S3与您的应用程序集成。

“入门指南”附带完整示例,并说明如何提供所需的凭据。

从概念上讲,Amazon S3将数据存储在存储桶中,其中存储桶包含对象。通常,每个应用程序将使用一个存储桶,并根据需要添加任意数量的对象。 S3不支持或具有任何文件夹概念,但您可以在对象名称中添加斜杠(/)。

答案 1 :(得分:8)

String      ACCESS_KEY="****************",
            SECRET_KEY="****************",
            MY_BUCKET="bucket_name",
            OBJECT_KEY="unique_id";              
  AWSCredentials credentials = new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY);
                AmazonS3 s3 = new AmazonS3Client(credentials);
                java.security.Security.setProperty("networkaddress.cache.ttl" , "60");
                s3.setRegion(Region.getRegion(Regions.AP_SOUTHEAST_1));
                s3.setEndpoint("https://s3-ap-southeast-1.amazonaws.com/");
                List<Bucket> buckets=s3.listBuckets();
                for(Bucket bucket:buckets){
                    Log.e("Bucket ","Name "+bucket.getName()+" Owner "+bucket.getOwner()+ " Date " + bucket.getCreationDate());
                }
                Log.e("Size ", "" + s3.listBuckets().size());
                TransferUtility transferUtility = new TransferUtility(s3, getApplicationContext());
                UPLOADING_IMAGE=new File(Environment.getExternalStorageDirectory().getPath()+"/Screenshot.png");
                TransferObserver observer = transferUtility.upload(MY_BUCKET,OBJECT_KEY,UPLOADING_IMAGE);
                observer.setTransferListener(new TransferListener() {
                    @Override
                    public void onStateChanged(int id, TransferState state) {
                        // do something
                        progress.hide();
                        path.setText("ID "+id+"\nState "+state.name()+"\nImage ID "+OBJECT_KEY);

                    }

                    @Override
                    public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) {
                        int percentage = (int) (bytesCurrent / bytesTotal * 100);
                        progress.setProgress(percentage);
                        //Display percentage transfered to user
                    }

                    @Override
                    public void onError(int id, Exception ex) {
                        // do something
                        Log.e("Error  ",""+ex );
                    }

                });

答案 2 :(得分:1)

我们可以直接使用“Amazone s3”存储桶在服务器上存储任何类型的文件,我们不需要向Api服务器发送任何文件,这将减少请求时间。

Gradle文件: -

 compile 'com.amazonaws:aws-android-sdk-core:2.2.+'
    compile 'com.amazonaws:aws-android-sdk-s3:2.2.+'
    compile 'com.amazonaws:aws-android-sdk-ddb:2.2.+'

清单文件: -

<service android:name="com.amazonaws.mobileconnectors.s3.transferutility.TransferService"
            android:enabled="true" />

任何类中的FileUploader函数: -

 private void setUPAmazon() {
 //we Need Identity Pool ID  like :- "us-east-1:f224****************8"
        CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(getActivity(),
                "us-east-1:f224****************8", Regions.US_EAST_1);
        AmazonS3 s3 = new AmazonS3Client(credentialsProvider);
        final TransferUtility transferUtility = new TransferUtility(s3, getActivity());
        final File file = new File(mCameraUri.getPath());
        final TransferObserver observer = transferUtility.upload(GeneralValues.AMAZON_BUCKET, file.getName(), file, CannedAccessControlList.PublicRead);
        observer.setTransferListener(new TransferListener() {
            @Override
            public void onStateChanged(int id, TransferState state) {
                Log.e("onStateChanged", id + state.name());
                if (state == TransferState.COMPLETED) {
                    String url = "https://"+GeneralValues.AMAZON_BUCKET+".s3.amazonaws.com/" + observer.getKey();
                    Log.e("URL :,", url);
//we just need to share this File url with Api service request.  
                }
            }

            @Override
            public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) {
            }

            @Override
            public void onError(int id, Exception ex) {
                Toast.makeText(getActivity(), "Unable to Upload", Toast.LENGTH_SHORT).show();
                ex.printStackTrace();
            }
        });
    }

答案 3 :(得分:0)

您可以在s3亚马逊上传图片和下载图片。你创建一个简单的类使用这个WebserviceAmazon

    WebserviceAmazon amazon = new WebserviceAmazon(getActivity(), imageName, "", 2);
    amazon.result(new WebserviceAmazon.WebServiceInterface<String, String>() {
        @Override
        public void success(String reslut) {

        }

        @Override
        public void error(String Error) {

        }
    });

    return totalPoints;
}

在项目

中的任何位置调用此Web服务
#include <iostream>
using namespace std;
class HashTable {
public:
    void Insert(int x)   {
      Find(x);
    }
    virtual int Find(int x)    {
        cout<<"base hash find \n";
        return x;    }
};

class SingleHash : public HashTable {
public:
     int Find(int x)    {
        cout<<"single hash find \n";      
        return x*2;
    }
};

class DoubleHash : public HashTable {
public:
     int Find(int x)    {
        cout<<"DOuble hash find \n";      
        return x*3;    }
};
int main(int argc, char** argv)
{
    int value;
    HashTable *hsingle = new SingleHash;
    cin >> value;
    hsingle->Insert(value);
    HashTable *hdouble = new DoubleHash;
    hdouble->Insert(value);
    return 0;
}

答案 4 :(得分:0)

您可以使用名为S3UploadService的库。首先,您需要将Bitmap转换为File。为此,请看一下这篇文章:

Convert Bitmap to File

S3UploadService是一个处理上传到Amazon S3的库。它提供了一个名为S3UploadService的服务,其中包含一个静态方法,您可以在其中提供一个Context(因此静态方法可以启动该服务),一个File,一个布尔值,指示在上传完成后是否应该删除所述文件,并且可以选择设置一个回调(Not就像普通的回调一样。它的工作方式在README文件中有解释。

这是一个IntentService,所以即使用户在上传时杀死了应用程序,上传也会运行(因为它的生命周期没有附加到应用程序的生命周期)。

要使用此库,您只需在清单中声明服务:

<application
    ...>

    ...

    <service
        android:name="com.onecode.s3.service.S3UploadService"
        android:exported="false" />
</application>

然后构建一个S3BucketData实例并调用S3UploadService.upload():

    S3Credentials s3Credentials = new S3Credentials(accessKey, secretKey, sessionToken);
    S3BucketData s3BucketData = new S3BucketData.Builder()
            .setCredentials(s3Credentials)
            .setBucket(bucket)
            .setKey(key)
            .setRegion(region)
            .build();

    S3UploadService.upload(getActivity(), s3BucketData, file, null);

要添加此库,您需要将JitPack存储库添加到根build.gradle:

allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}

然后添加依赖项:

dependencies {
    compile 'com.github.OneCodeLabs:S3UploadService:1.0.0@aar'
}

这是回购的链接: https://github.com/OneCodeLabs/S3UploadService

这个答案有点晚了,但我希望它有助于某人

答案 5 :(得分:0)

您可以使用下面提到的类将数据上传到Amazon s3存储桶。

public class UploadAmazonS3{

private CognitoCachingCredentialsProvider credentialsProvider = null;
private AmazonS3Client s3Client = null;
private TransferUtility transferUtility = null;
private static UploadAmazonS3 uploadAmazonS3;

/**
 * Creating single tone object by defining private.
 * <P>
 *     At the time of creating
 * </P>*/
private UploadAmazonS3(Context context, String canito_pool_id)
{
    /**
     * Creating the object of the getCredentialProvider object. */
    credentialsProvider=getCredentialProvider(context,canito_pool_id);
    /**
     * Creating the object  of the s3Client */
    s3Client=getS3Client(context,credentialsProvider);

    /**
     * Creating the object of the TransferUtility of the Amazone.*/
    transferUtility=getTransferUtility(context,s3Client);

}

public static UploadAmazonS3 getInstance(Context context, String canito_pool_id)
{
    if(uploadAmazonS3 ==null)
    {
        uploadAmazonS3 =new UploadAmazonS3(context,canito_pool_id);
        return uploadAmazonS3;
    }else
    {
        return uploadAmazonS3;
    }

}

/**
 * <h3>Upload_data</h3>
 * <P>
 *     Method is use to upload data in the amazone server.
 *
 * </P>*/

public void uploadData(final String bukkate_name, final File file, final Upload_CallBack callBack)
{
    Utility.printLog("in amazon upload class uploadData "+file.getName());

    if(transferUtility!=null&&file!=null)
    {
        TransferObserver observer=transferUtility.upload(bukkate_name,file.getName(),file);
        observer.setTransferListener(new TransferListener()
        {
            @Override
            public void onStateChanged(int id, TransferState state)
            {
                if(state.equals(TransferState.COMPLETED))
                {
                    callBack.sucess(com.tarha_taxi.R.string.AMAZON_END_POINT_LINK+bukkate_name+"/"+file.getName());
                }
            }

            @Override
            public void onProgressChanged(int id, long bytesCurrent, long bytesTotal)
            {

            }
            @Override
            public void onError(int id, Exception ex)
            {
                callBack.error(id+":"+ex.toString());

            }
        });
    }else
    {
        callBack.error("Amamzones3 is not intialize or File is empty !");
    }
}

/**
 * This method is used to get the CredentialProvider and we provide only context as a parameter.
 * @param context Here, we are getting the context from calling Activity.*/
private CognitoCachingCredentialsProvider getCredentialProvider(Context context,String pool_id)
{
    if (credentialsProvider == null)
    {
        credentialsProvider = new CognitoCachingCredentialsProvider(
                context.getApplicationContext(),
                pool_id, // Identity Pool ID
                AMAZON_REGION // Region
        );
    }
    return credentialsProvider;
}

/**
 * This method is used to get the AmazonS3 Client
 * and we provide only context as a parameter.
 * and from here we are calling getCredentialProvider() function.
 * @param context Here, we are getting the context from calling Activity.*/
private AmazonS3Client getS3Client(Context context,CognitoCachingCredentialsProvider cognitoCachingCredentialsProvider)
{
    if (s3Client == null)
    {
        s3Client = new AmazonS3Client(cognitoCachingCredentialsProvider);
        s3Client.setRegion(Region.getRegion(AMAZON_REGION));
        s3Client.setEndpoint(context.getString(com.tarha_taxi.R.string.AMAZON_END_POINT_LINK));
    }
    return s3Client;
}

/**
 * This method is used to get the Transfer Utility
 * and we provide only context as a parameter.
 * and from here we are, calling getS3Client() function.
 * @param context Here, we are getting the context from calling Activity.*/
private TransferUtility getTransferUtility(Context context,AmazonS3Client amazonS3Client)
{
    if (transferUtility == null)
    {
        transferUtility = new TransferUtility(amazonS3Client,context.getApplicationContext());
    }
    return transferUtility;
}

/**
 * Interface for the sucess callback fro the Amazon uploading .
 * */
public interface Upload_CallBack
{
    /**
     *Method for sucess .
     * @param sucess it is true on sucess and false for falure.*/
    void sucess(String sucess);
    /**
     * Method for falure.
     * @param errormsg contains the error message.*/
    void error(String errormsg);

}

}

使用下面的方法访问上面的内容:

 private void uploadToAmazon() {
    dialogL.show();
    UploadAmazonS3 amazonS3 = UploadAmazonS3.getInstance(getActivity(), getString(R.string.AMAZON_POOL_ID));
    amazonS3.uploadData(getString(R.string.BUCKET_NAME), Utility.renameFile(VariableConstants.TEMP_PHOTO_FILE_NAME, phone.getText().toString().substring(1) + ".jpg"), new UploadAmazonS3.Upload_CallBack() {
        @Override
        public void sucess(String sucess) {
            if (Utility.isNetworkAvailable(getActivity())) {
                dialogL.dismiss();
                /**
                 * to set the image into image view and
                 * add the write the image in the file
                 */
                activity.user_image.setTag(setTarget(progress_bar));
                Picasso.with(getActivity()).load(getString(R.string.AMAZON_IMAGE_LINK) + phone.getText().toString().substring(1) + ".jpg").
                        networkPolicy(NetworkPolicy.NO_CACHE).memoryPolicy(MemoryPolicy.NO_CACHE).into((Target) activity.user_image.getTag());

                Utility.printLog("amazon upload success ");
                new BackgroundForUpdateProfile().execute();
            } else {
                dialogL.dismiss();
                Utility.showToast(getActivity(), getResources().getString(R.string.network_connection_fail));
            }
        }

        @Override
        public void error(String errormsg) {
            dialogL.dismiss();
            Utility.showToast(getActivity(), getResources().getString(R.string.network_connection_fail));
        }
    });
}

答案 6 :(得分:0)

这是我将图像上传到 Amazon AWS S3 存储桶的代码 希望这对你有帮助 首先让我明确一些关键点 您可以从相机拍摄图像或从图库中选择图像,AWS 将图像存储为文件,因此首先需要将图像存储到本地目录并获取图像路径,然后从该路径创建一个文件,然后您就可以上传将该图像文件发送到 AWS。

首先你需要在Oncreate

上添加配置
BasicAWSCredentials credentials = new BasicAWSCredentials(KEY,SECRET);
         s3 = new AmazonS3Client(credentials);
        s3.setRegion(Region.getRegion(Regions.US_EAST_1));

private void uploadFile() {

        verifyStoragePermissions(CustomCameraActivity.this);

        TransferUtility transferUtility =
                TransferUtility.builder()
                        .context(getApplicationContext())
                        .awsConfiguration(AWSMobileClient.getInstance().getConfiguration())
                        .s3Client(s3)
                        .build();

        TransferObserver uploadObserver= null;
        
        File file2 = FileUtils.getFile(CustomCameraActivity.this, storageImagePath);//here i am converting path to file ,,FileUtils.getFile is custom class
        
            uploadObserver = transferUtility.upload("your bucket name", imageNameWithoutExtension + ".jpg", file2);// imagenamewithoutExtension is actually the name that you want to store 

        uploadObserver.setTransferListener(new TransferListener() {

            @Override
            public void onStateChanged(int id, TransferState state) {
                if (TransferState.COMPLETED == state) {
                    Toast.makeText(getApplicationContext(), "Upload Completed!", Toast.LENGTH_SHORT).show();
                    uploadResourcesApi(uploadResoucesURL);
                    //imageFile.delete();
                    //file2.delete();
                } else if (TransferState.FAILED == state) {
                    //imageFile.delete();
                    //file2.delete();
                }
            }

            @Override
            public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) {
                float percentDonef = ((float) bytesCurrent / (float) bytesTotal) * 100;
                int percentDone = (int) percentDonef;

                //tvFileName.setText("ID:" + id + "|bytesCurrent: " + bytesCurrent + "|bytesTotal: " + bytesTotal + "|" + percentDone + "%");
            }

            @Override
            public void onError(int id, Exception ex) {
                ex.printStackTrace();
            }

        });
    } 

这是 fileUtils 类

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.Log;
import android.webkit.MimeTypeMap;



import java.io.File;
import java.io.FileFilter;
import java.text.DecimalFormat;
import java.util.Comparator;

/**
 * @version 2009-07-03
 * @author Peli
 * @version 2013-12-11
 * @author paulburke (ipaulpro)
 */
public class FileUtils {
    private FileUtils() {} //private constructor to enforce Singleton pattern

    /** TAG for log messages. */
    static final String TAG = "FileUtils";
    private static final boolean DEBUG = false; // Set to true to enable logging

    public static final String MIME_TYPE_AUDIO = "audio/*";
    public static final String MIME_TYPE_TEXT = "text/*";
    public static final String MIME_TYPE_IMAGE = "image/*";
    public static final String MIME_TYPE_VIDEO = "video/*";
    public static final String MIME_TYPE_APP = "application/*";

    public static final String HIDDEN_PREFIX = ".";

    /**
     * Gets the extension of a file name, like ".png" or ".jpg".
     *
     * @param uri
     * @return Extension including the dot("."); "" if there is no extension;
     *         null if uri was null.
     */
    public static String getExtension(String uri) {
        if (uri == null) {
            return null;
        }

        int dot = uri.lastIndexOf(".");
        if (dot >= 0) {
            return uri.substring(dot);
        } else {
            // No extension.
            return "";
        }
    }

    /**
     * @return Whether the URI is a local one.
     */
    public static boolean isLocal(String url) {
        if (url != null && !url.startsWith("http://") && !url.startsWith("https://")) {
            return true;
        }
        return false;
    }

    /**
     * @return True if Uri is a MediaStore Uri.
     * @author paulburke
     */
    public static boolean isMediaUri(Uri uri) {
        return "media".equalsIgnoreCase(uri.getAuthority());
    }

    /**
     * Convert File into Uri.
     *
     * @param file
     * @return uri
     */
    public static Uri getUri(File file) {
        if (file != null) {
            return Uri.fromFile(file);
        }
        return null;
    }

    /**
     * Returns the path only (without file name).
     *
     * @param file
     * @return
     */
    public static File getPathWithoutFilename(File file) {
        if (file != null) {
            if (file.isDirectory()) {
                // no file to be split off. Return everything
                return file;
            } else {
                String filename = file.getName();
                String filepath = file.getAbsolutePath();

                // Construct path without file name.
                String pathwithoutname = filepath.substring(0,
                        filepath.length() - filename.length());
                if (pathwithoutname.endsWith("/")) {
                    pathwithoutname = pathwithoutname.substring(0, pathwithoutname.length() - 1);
                }
                return new File(pathwithoutname);
            }
        }
        return null;
    }

    /**
     * @return The MIME type for the given file.
     */
    public static String getMimeType(File file) {

        String extension = getExtension(file.getName());

        if (extension.length() > 0)
            return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.substring(1));

        return "application/octet-stream";
    }

    /**
     * @return The MIME type for the give Uri.
     */
    public static String getMimeType(Context context, Uri uri) {
        File file = new File(getPath(context, uri));
        return getMimeType(file);
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is {@link LocalStorageProvider}.
     * @author paulburke
     */
    public static boolean isLocalStorageDocument(Uri uri) {
        return LocalStorageProvider.AUTHORITY.equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     * @author paulburke
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     * @author paulburke
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     * @author paulburke
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context The context.
     * @param uri The Uri to query.
     * @param selection (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     * @author paulburke
     */
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                if (DEBUG)
                    DatabaseUtils.dumpCursor(cursor);

                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    
    public static String getPath(final Context context, final Uri uri) {

        if (DEBUG)
            Log.d(TAG + " File -",
                    "Authority: " + uri.getAuthority() +
                            ", Fragment: " + uri.getFragment() +
                            ", Port: " + uri.getPort() +
                            ", Query: " + uri.getQuery() +
                            ", Scheme: " + uri.getScheme() +
                            ", Host: " + uri.getHost() +
                            ", Segments: " + uri.getPathSegments().toString()
            );

        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // LocalStorageProvider
            if (isLocalStorageDocument(uri)) {
                // The path is the id
                return DocumentsContract.getDocumentId(uri);
            }
            // ExternalStorageProvider
            else if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }

                // TODO handle non-primary volumes
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[] {
                        split[1]
                };

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {

            // Return the remote address
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();

            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    
    public static File getFile(Context context, Uri uri) {
        if (uri != null) {
            String path = getPath(context, uri);
            if (path != null && isLocal(path)) {
                return new File(path);
            }
        }
        return null;
    }

    
    public static String getReadableFileSize(int size) {
        final int BYTES_IN_KILOBYTES = 1024;
        final DecimalFormat dec = new DecimalFormat("###.#");
        final String KILOBYTES = " KB";
        final String MEGABYTES = " MB";
        final String GIGABYTES = " GB";
        float fileSize = 0;
        String suffix = KILOBYTES;

        if (size > BYTES_IN_KILOBYTES) {
            fileSize = size / BYTES_IN_KILOBYTES;
            if (fileSize > BYTES_IN_KILOBYTES) {
                fileSize = fileSize / BYTES_IN_KILOBYTES;
                if (fileSize > BYTES_IN_KILOBYTES) {
                    fileSize = fileSize / BYTES_IN_KILOBYTES;
                    suffix = GIGABYTES;
                } else {
                    suffix = MEGABYTES;
                }
            }
        }
        return String.valueOf(dec.format(fileSize) + suffix);
    }

    
    public static Bitmap getThumbnail(Context context, File file) {
        return getThumbnail(context, getUri(file), getMimeType(file));
    }

    
    public static Bitmap getThumbnail(Context context, Uri uri) {
        return getThumbnail(context, uri, getMimeType(context, uri));
    }

    
    public static Bitmap getThumbnail(Context context, Uri uri, String mimeType) {
        if (DEBUG)
            Log.d(TAG, "Attempting to get thumbnail");

        if (!isMediaUri(uri)) {
            Log.e(TAG, "You can only retrieve thumbnails for images and videos.");
            return null;
        }

        Bitmap bm = null;
        if (uri != null) {
            final ContentResolver resolver = context.getContentResolver();
            Cursor cursor = null;
            try {
                cursor = resolver.query(uri, null, null, null, null);
                if (cursor.moveToFirst()) {
                    final int id = cursor.getInt(0);
                    if (DEBUG)
                        Log.d(TAG, "Got thumb ID: " + id);

                    if (mimeType.contains("video")) {
                        bm = MediaStore.Video.Thumbnails.getThumbnail(
                                resolver,
                                id,
                                MediaStore.Video.Thumbnails.MINI_KIND,
                                null);
                    }
                    else if (mimeType.contains(FileUtils.MIME_TYPE_IMAGE)) {
                        bm = MediaStore.Images.Thumbnails.getThumbnail(
                                resolver,
                                id,
                                MediaStore.Images.Thumbnails.MINI_KIND,
                                null);
                    }
                }
            } catch (Exception e) {
                if (DEBUG)
                    Log.e(TAG, "getThumbnail", e);
            } finally {
                if (cursor != null)
                    cursor.close();
            }
        }
        return bm;
    }

    
    public static Comparator<File> sComparator = new Comparator<File>() {
        @Override
        public int compare(File f1, File f2) {
            // Sort alphabetically by lower case, which is much cleaner
            return f1.getName().toLowerCase().compareTo(
                    f2.getName().toLowerCase());
        }
    };

   
    public static FileFilter sFileFilter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            final String fileName = file.getName();
            // Return files only (not directories) and skip hidden files
            return file.isFile() && !fileName.startsWith(HIDDEN_PREFIX);
        }
    };

    
    public static FileFilter sDirFilter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            final String fileName = file.getName();
            // Return directories only and skip hidden directories
            return file.isDirectory() && !fileName.startsWith(HIDDEN_PREFIX);
        }
    };

    
    public static Intent createGetContentIntent() {
        // Implicitly allow the user to select a particular kind of data
        final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        // The MIME data type filter
        intent.setType("*/*");
        // Only return URIs that can be opened with ContentResolver
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        return intent;
    }
}

那么你也需要这个类

public class LocalStorageProvider extends DocumentsProvider {

    public static final String AUTHORITY = "com.ianhanniballake.localstorage.documents";

    private final static String[] DEFAULT_ROOT_PROJECTION = new String[] {
            Root.COLUMN_ROOT_ID,
            Root.COLUMN_FLAGS, Root.COLUMN_TITLE, Root.COLUMN_DOCUMENT_ID, Root.COLUMN_ICON,
            Root.COLUMN_AVAILABLE_BYTES
    };
    
    private final static String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
            Document.COLUMN_DOCUMENT_ID,
            Document.COLUMN_DISPLAY_NAME, Document.COLUMN_FLAGS, Document.COLUMN_MIME_TYPE,
            Document.COLUMN_SIZE,
            Document.COLUMN_LAST_MODIFIED
    };

    @Override
    public Cursor queryRoots(final String[] projection) throws FileNotFoundException {
        
        final MatrixCursor result = new MatrixCursor(projection != null ? projection
                : DEFAULT_ROOT_PROJECTION);
        
        File homeDir = Environment.getExternalStorageDirectory();
        final MatrixCursor.RowBuilder row = result.newRow();
        // These columns are required
        row.add(Root.COLUMN_ROOT_ID, homeDir.getAbsolutePath());
        row.add(Root.COLUMN_DOCUMENT_ID, homeDir.getAbsolutePath());
        row.add(Root.COLUMN_TITLE, "Internal storage");
        row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_CREATE);
        row.add(Root.COLUMN_ICON, R.drawable.ic_launcher_foreground);
        // These columns are optional
        row.add(Root.COLUMN_AVAILABLE_BYTES, homeDir.getFreeSpace());
        // Root.COLUMN_MIME_TYPE is another optional column and useful if you
        
        return result;
    }

    @Override
    public String createDocument(final String parentDocumentId, final String mimeType,
                                 final String displayName) throws FileNotFoundException {
        File newFile = new File(parentDocumentId, displayName);
        try {
            newFile.createNewFile();
            return newFile.getAbsolutePath();
        } catch (IOException e) {
            Log.e(LocalStorageProvider.class.getSimpleName(), "Error creating new file " + newFile);
        }
        return null;
    }

    @Override
    public AssetFileDescriptor openDocumentThumbnail(final String documentId, final Point sizeHint,
                                                     final CancellationSignal signal) throws FileNotFoundException {
        
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(documentId, options);
        final int targetHeight = 2 * sizeHint.y;
        final int targetWidth = 2 * sizeHint.x;
        final int height = options.outHeight;
        final int width = options.outWidth;
        options.inSampleSize = 1;
        if (height > targetHeight || width > targetWidth) {
            final int halfHeight = height / 2;
            final int halfWidth = width / 2;
           
            while ((halfHeight / options.inSampleSize) > targetHeight
                    || (halfWidth / options.inSampleSize) > targetWidth) {
                options.inSampleSize *= 2;
            }
        }
        options.inJustDecodeBounds = false;
        Bitmap bitmap = BitmapFactory.decodeFile(documentId, options);
        // Write out the thumbnail to a temporary file
        File tempFile = null;
        FileOutputStream out = null;
        try {
            tempFile = File.createTempFile("thumbnail", null, getContext().getCacheDir());
            out = new FileOutputStream(tempFile);
            bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
        } catch (IOException e) {
            Log.e(LocalStorageProvider.class.getSimpleName(), "Error writing thumbnail", e);
            return null;
        } finally {
            if (out != null)
                try {
                    out.close();
                } catch (IOException e) {
                    Log.e(LocalStorageProvider.class.getSimpleName(), "Error closing thumbnail", e);
                }
        }
        // It appears the Storage Framework UI caches these results quite
        // aggressively so there is little reason to
        // write your own caching layer beyond what you need to return a single
        // AssetFileDescriptor
        return new AssetFileDescriptor(ParcelFileDescriptor.open(tempFile,
                ParcelFileDescriptor.MODE_READ_ONLY), 0,
                AssetFileDescriptor.UNKNOWN_LENGTH);
    }

    @Override
    public Cursor queryChildDocuments(final String parentDocumentId, final String[] projection,
                                      final String sortOrder) throws FileNotFoundException {
        // Create a cursor with either the requested fields, or the default
        // projection if "projection" is null.
        final MatrixCursor result = new MatrixCursor(projection != null ? projection
                : DEFAULT_DOCUMENT_PROJECTION);
        final File parent = new File(parentDocumentId);
        for (File file : parent.listFiles()) {
            // Don't show hidden files/folders
            if (!file.getName().startsWith(".")) {
                // Adds the file's display name, MIME type, size, and so on.
                includeFile(result, file);
            }
        }
        return result;
    }

    @Override
    public Cursor queryDocument(final String documentId, final String[] projection)
            throws FileNotFoundException {
        // Create a cursor with either the requested fields, or the default
        // projection if "projection" is null.
        final MatrixCursor result = new MatrixCursor(projection != null ? projection
                : DEFAULT_DOCUMENT_PROJECTION);
        includeFile(result, new File(documentId));
        return result;
    }

    private void includeFile(final MatrixCursor result, final File file)
            throws FileNotFoundException {
        final MatrixCursor.RowBuilder row = result.newRow();
        // These columns are required
        row.add(Document.COLUMN_DOCUMENT_ID, file.getAbsolutePath());
        row.add(Document.COLUMN_DISPLAY_NAME, file.getName());
        String mimeType = getDocumentType(file.getAbsolutePath());
        row.add(Document.COLUMN_MIME_TYPE, mimeType);
        int flags = file.canWrite() ? Document.FLAG_SUPPORTS_DELETE | Document.FLAG_SUPPORTS_WRITE
                : 0;
        // We only show thumbnails for image files - expect a call to
        // openDocumentThumbnail for each file that has
        // this flag set
        if (mimeType.startsWith("image/"))
            flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
        row.add(Document.COLUMN_FLAGS, flags);
        // COLUMN_SIZE is required, but can be null
        row.add(Document.COLUMN_SIZE, file.length());
        // These columns are optional
        row.add(Document.COLUMN_LAST_MODIFIED, file.lastModified());
        // Document.COLUMN_ICON can be a resource id identifying a custom icon.
        // The system provides default icons
        // based on mime type
        // Document.COLUMN_SUMMARY is optional additional information about the
        // file
    }

    @Override
    public String getDocumentType(final String documentId) throws FileNotFoundException {
        File file = new File(documentId);
        if (file.isDirectory())
            return Document.MIME_TYPE_DIR;
        // From FileProvider.getType(Uri)
        final int lastDot = file.getName().lastIndexOf('.');
        if (lastDot >= 0) {
            final String extension = file.getName().substring(lastDot + 1);
            final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
            if (mime != null) {
                return mime;
            }
        }
        return "application/octet-stream";
    }

    @Override
    public void deleteDocument(final String documentId) throws FileNotFoundException {
        new File(documentId).delete();
    }

    @Override
    public ParcelFileDescriptor openDocument(final String documentId, final String mode,
                                             final CancellationSignal signal) throws FileNotFoundException {
        File file = new File(documentId);
        final boolean isWrite = (mode.indexOf('w') != -1);
        if (isWrite) {
            return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE);
        } else {
            return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
        }
    }

    @Override
    public boolean onCreate() {
        return true;
    }
}