1 /*
2  * Copyright 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.example.android.receivecontent;
18 
19 import android.content.ContentResolver;
20 import android.content.Context;
21 import android.net.Uri;
22 import android.util.Log;
23 import android.webkit.MimeTypeMap;
24 
25 import androidx.annotation.NonNull;
26 import androidx.core.content.FileProvider;
27 
28 import com.google.common.collect.ImmutableList;
29 import com.google.common.io.ByteStreams;
30 
31 import java.io.File;
32 import java.io.FileOutputStream;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.OutputStream;
36 import java.util.UUID;
37 
38 /**
39  * Stores attachments as files in the app's private storage directory (see
40  * {@link Context#getDataDir()}, {@link Context#getFilesDir()}, etc).
41  */
42 final class AttachmentsRepo {
43 
44     // This matches the name declared in AndroidManifest.xml
45     private static final String FILE_PROVIDER_AUTHORITY =
46             "com.example.android.receivecontent.fileprovider";
47 
48     private final Context mContext;
49     private final File mAttachmentsDir;
50 
AttachmentsRepo(@onNull Context context)51     AttachmentsRepo(@NonNull Context context) {
52         mContext = context;
53         mAttachmentsDir = new File(mContext.getFilesDir(), "attachments");
54     }
55 
56     /**
57      * Reads the content at the given URI and writes it to private storage. Then returns a content
58      * URI referencing the newly written file.
59      */
60     @NonNull
write(@onNull Uri uri)61     public Uri write(@NonNull Uri uri) {
62         ContentResolver contentResolver = mContext.getContentResolver();
63         String mimeType = contentResolver.getType(uri);
64         String ext = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType);
65         try (InputStream is = contentResolver.openInputStream(uri)) {
66             if (is == null) {
67                 throw new IllegalArgumentException(String.valueOf(uri));
68             }
69             mAttachmentsDir.mkdirs();
70             String fileName = "a-" + UUID.randomUUID().toString() + "." + ext;
71             File newAttachment = new File(mAttachmentsDir, fileName);
72             try (OutputStream os = new FileOutputStream(newAttachment);) {
73                 ByteStreams.copy(is, os);
74             }
75             Log.i(Logcat.TAG,
76                     "Wrote file [" + fileName + "]: " + newAttachment.length() + " bytes");
77             return getUriForFile(newAttachment);
78         } catch (IOException e) {
79             throw new IllegalStateException(e);
80         }
81 
82     }
83 
deleteAll()84     public void deleteAll() {
85         File[] files = mAttachmentsDir.listFiles();
86         if (files == null) {
87             return;
88         }
89         for (File file : files) {
90             file.delete();
91         }
92     }
93 
94     @NonNull
getAllUris()95     public ImmutableList<Uri> getAllUris() {
96         File[] files = mAttachmentsDir.listFiles();
97         if (files == null || files.length == 0) {
98             return ImmutableList.of();
99         }
100         ImmutableList.Builder<Uri> uris = ImmutableList.builderWithExpectedSize(files.length);
101         for (File file : files) {
102             uris.add(getUriForFile(file));
103         }
104         return uris.build();
105     }
106 
107     @NonNull
getUriForFile(@onNull File file)108     private Uri getUriForFile(@NonNull File file) {
109         return FileProvider.getUriForFile(mContext, FILE_PROVIDER_AUTHORITY, file);
110     }
111 }
112