|
1 | 1 | package com.fox2code.mmm.utils; |
2 | 2 |
|
| 3 | +import android.annotation.SuppressLint; |
3 | 4 | import android.app.Activity; |
4 | 5 | import android.content.ActivityNotFoundException; |
5 | 6 | import android.content.ComponentName; |
| 7 | +import android.content.ContentResolver; |
6 | 8 | import android.content.Context; |
7 | 9 | import android.content.ContextWrapper; |
8 | 10 | import android.content.Intent; |
9 | 11 | import android.net.Uri; |
10 | 12 | import android.os.Bundle; |
| 13 | +import android.os.Environment; |
11 | 14 | import android.util.Log; |
12 | 15 | import android.widget.Toast; |
13 | 16 |
|
14 | 17 | import androidx.core.app.ActivityOptionsCompat; |
15 | 18 |
|
16 | 19 | import com.fox2code.mmm.Constants; |
17 | 20 | import com.fox2code.mmm.MainApplication; |
| 21 | +import com.fox2code.mmm.R; |
18 | 22 | import com.fox2code.mmm.compat.CompatActivity; |
19 | 23 | import com.fox2code.mmm.installer.InstallerActivity; |
20 | 24 | import com.fox2code.mmm.markdown.MarkdownActivity; |
| 25 | +import com.topjohnwu.superuser.io.SuFileInputStream; |
21 | 26 |
|
22 | 27 | import java.io.File; |
| 28 | +import java.io.FileInputStream; |
23 | 29 | import java.io.FileOutputStream; |
| 30 | +import java.io.IOException; |
24 | 31 | import java.io.InputStream; |
25 | 32 | import java.io.OutputStream; |
26 | 33 |
|
@@ -144,50 +151,78 @@ public static Activity getActivity(Context context) { |
144 | 151 | return (Activity) context; |
145 | 152 | } |
146 | 153 |
|
| 154 | + public static final int RESPONSE_ERROR = 0; |
| 155 | + public static final int RESPONSE_FILE = 1; |
| 156 | + public static final int RESPONSE_URL = 2; |
| 157 | + |
| 158 | + @SuppressLint("SdCardPath") |
147 | 159 | public static void openFileTo(CompatActivity compatActivity, File destination, |
148 | | - OnFileReceivedCallback callback) { |
| 160 | + OnFileReceivedCallback callback) { |
149 | 161 | Intent intent = new Intent(Intent.ACTION_GET_CONTENT).setType("application/zip"); |
150 | 162 | intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK); |
151 | | - intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true); |
| 163 | + intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false); |
| 164 | + intent.putExtra(Intent.EXTRA_LOCAL_ONLY, false); |
152 | 165 | intent.addCategory(Intent.CATEGORY_OPENABLE); |
153 | 166 | Bundle param = ActivityOptionsCompat.makeCustomAnimation(compatActivity, |
154 | 167 | android.R.anim.fade_in, android.R.anim.fade_out).toBundle(); |
155 | 168 | compatActivity.startActivityForResult(intent, param, (result, data) -> { |
156 | | - String name = destination.getName(); |
157 | | - if (data == null || result != Activity.RESULT_OK) { |
158 | | - callback.onReceived(destination, false); |
| 169 | + Uri uri = data == null ? null : data.getData(); |
| 170 | + if (uri == null || (result == Activity.RESULT_CANCELED && !(( |
| 171 | + ContentResolver.SCHEME_FILE.equals(uri.getScheme()) |
| 172 | + && uri.getPath() != null && |
| 173 | + (uri.getPath().startsWith("/sdcard/") || |
| 174 | + uri.getPath().startsWith("/data/")) |
| 175 | + ) || ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme())))) { |
| 176 | + callback.onReceived(destination, null, RESPONSE_ERROR); |
159 | 177 | return; |
160 | 178 | } |
161 | | - Uri uri = data.getData(); |
162 | | - if (uri == null || "http".equals(uri.getScheme()) || |
| 179 | + Log.d("IntentHelper", "FilePicker returned " + uri.toString()); |
| 180 | + if ("http".equals(uri.getScheme()) || |
163 | 181 | "https".equals(uri.getScheme())) { |
164 | | - callback.onReceived(destination, false); |
| 182 | + callback.onReceived(destination, uri, RESPONSE_URL); |
165 | 183 | return; |
166 | 184 | } |
| 185 | + if (ContentResolver.SCHEME_FILE.equals(uri.getScheme()) || |
| 186 | + (result != Activity.RESULT_OK && result != Activity.RESULT_FIRST_USER)) { |
| 187 | + Toast.makeText(compatActivity, |
| 188 | + R.string.file_picker_wierd, |
| 189 | + Toast.LENGTH_SHORT).show(); |
| 190 | + } |
167 | 191 | InputStream inputStream = null; |
168 | 192 | OutputStream outputStream = null; |
169 | 193 | boolean success = false; |
170 | 194 | try { |
171 | | - inputStream = compatActivity.getContentResolver() |
172 | | - .openInputStream(uri); |
| 195 | + if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { |
| 196 | + String path = uri.getPath(); |
| 197 | + if (path.startsWith("/sdcard/")) { // Fix file paths |
| 198 | + path = Environment.getExternalStorageDirectory() |
| 199 | + .getAbsolutePath() + path.substring(7); |
| 200 | + } |
| 201 | + inputStream = SuFileInputStream.open( |
| 202 | + new File(path).getAbsoluteFile()); |
| 203 | + } else { |
| 204 | + inputStream = compatActivity.getContentResolver() |
| 205 | + .openInputStream(uri); |
| 206 | + } |
173 | 207 | outputStream = new FileOutputStream(destination); |
174 | 208 | Files.copy(inputStream, outputStream); |
175 | | - String newName = uri.getLastPathSegment(); |
176 | | - if (newName.endsWith(".zip")) name = newName; |
177 | 209 | success = true; |
178 | 210 | } catch (Exception e) { |
179 | 211 | Log.e("IntentHelper", "fail copy", e); |
| 212 | + Toast.makeText(compatActivity, |
| 213 | + R.string.file_picker_failure, |
| 214 | + Toast.LENGTH_SHORT).show(); |
180 | 215 | } finally { |
181 | 216 | Files.closeSilently(inputStream); |
182 | 217 | Files.closeSilently(outputStream); |
183 | 218 | if (!success && destination.exists() && !destination.delete()) |
184 | 219 | Log.e("IntentHelper", "Failed to delete artefact!"); |
185 | 220 | } |
186 | | - callback.onReceived(destination, success); |
| 221 | + callback.onReceived(destination, uri, success ? RESPONSE_FILE : RESPONSE_ERROR); |
187 | 222 | }); |
188 | 223 | } |
189 | 224 |
|
190 | 225 | public interface OnFileReceivedCallback { |
191 | | - void onReceived(File target,boolean success); |
| 226 | + void onReceived(File target,Uri uri,int response); |
192 | 227 | } |
193 | 228 | } |
0 commit comments