1 /* 2 * Copyright 2024 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 androidx.pdf.data; 18 19 import android.net.Uri; 20 import android.os.Parcel; 21 import android.os.ParcelFileDescriptor; 22 import android.os.Parcelable; 23 24 import androidx.annotation.RestrictTo; 25 import androidx.pdf.util.Preconditions; 26 import androidx.pdf.util.Uris; 27 28 import org.jspecify.annotations.NonNull; 29 import org.jspecify.annotations.Nullable; 30 31 import java.io.File; 32 import java.io.FileInputStream; 33 import java.io.FileNotFoundException; 34 import java.io.IOException; 35 import java.io.InputStream; 36 37 /** 38 * A file's data that is saved on disk (e.g. in cache). 39 */ 40 @RestrictTo(RestrictTo.Scope.LIBRARY) 41 public class FileOpenable implements Openable, Parcelable { 42 43 private static final String TAG = FileOpenable.class.getSimpleName(); 44 45 /** 46 * Turns this {@link Uri} into a {@link File} if possible 47 * 48 * @throws IllegalArgumentException If the Uri was not a 'file:' one. 49 */ getFile(Uri fileUri)50 private static File getFile(Uri fileUri) { 51 Preconditions.checkArgument(Uris.isFileUri(fileUri), 52 "FileOpenable only valid for file Uris"); 53 return new File(fileUri.getPath()); 54 } 55 56 private final @Nullable String mContentType; 57 58 private final File mFile; 59 60 /** 61 * Constructs an {@link Openable} from a file and a given content-type. 62 * 63 * @throws FileNotFoundException If the file does not exist. 64 */ FileOpenable(@onNull File file, @Nullable String mimeType)65 public FileOpenable(@NonNull File file, @Nullable String mimeType) 66 throws FileNotFoundException { 67 if (!file.exists()) { 68 throw new FileNotFoundException("file does not exist"); 69 } 70 this.mFile = Preconditions.checkNotNull(file); 71 this.mContentType = mimeType; 72 } 73 74 /** 75 * Constructs an {@link Openable} from a file Uri. 76 * 77 * @throws IllegalArgumentException If the Uri was not a 'file:' one. 78 * @throws FileNotFoundException If the file does not exist. 79 */ FileOpenable(@onNull Uri uri)80 public FileOpenable(@NonNull Uri uri) throws FileNotFoundException { 81 this(getFile(uri), Uris.extractContentType(uri)); 82 } 83 84 @Override openWith(@onNull Opener opener)85 public @NonNull Open openWith(@NonNull Opener opener) throws IOException { 86 return new Open() { 87 88 @Override 89 public InputStream getInputStream() throws IOException { 90 return new FileInputStream(mFile); 91 } 92 93 @Override 94 public ParcelFileDescriptor getFd() throws IOException { 95 return ParcelFileDescriptor.open(mFile, ParcelFileDescriptor.MODE_READ_ONLY); 96 } 97 98 @Override 99 public long length() { 100 return mFile.length(); 101 } 102 103 @Override 104 public String getContentType() { 105 return mContentType; 106 } 107 }; 108 } 109 110 @Override 111 public @Nullable String getContentType() { 112 return mContentType; 113 } 114 115 @Override 116 public long length() { 117 return mFile.length(); 118 } 119 120 public @NonNull String getFileName() { 121 return mFile.getName(); 122 } 123 124 public @NonNull Uri getFileUri() { 125 return Uri.fromFile(mFile); 126 } 127 128 129 @Override 130 public void writeToParcel(@NonNull Parcel dest, int flags) { 131 dest.writeString(mFile.getPath()); 132 dest.writeString(mContentType); 133 } 134 135 @Override 136 public int describeContents() { 137 return 0; 138 } 139 140 public static final Creator<FileOpenable> CREATOR = 141 new Creator<FileOpenable>() { 142 @Override 143 public @Nullable FileOpenable createFromParcel(Parcel parcel) { 144 try { 145 return new FileOpenable(makeFile(parcel.readString()), parcel.readString()); 146 } catch (FileNotFoundException e) { 147 return null; 148 } 149 } 150 151 private File makeFile(String filePath) { 152 return new File(filePath); 153 } 154 155 @Override 156 public FileOpenable[] newArray(int size) { 157 return new FileOpenable[size]; 158 } 159 }; 160 } 161