-
Notifications
You must be signed in to change notification settings - Fork 9.7k
[image_picker] Change storage location for camera captures to internal cache on Android, to comply with new Google Play storage requirements. #3956
Changes from 9 commits
7be1c7c
d79bac3
df306e2
467bb5c
b2e902e
84a5ad1
46df81f
15d841d
e1cb24e
eafa023
aa3c24d
a3c737c
bc3e4d5
121a7ca
1143108
bfb2b6a
e973353
ca846ba
fa3c577
80906ca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,10 @@ | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
package="io.flutter.plugins.imagepicker"> | ||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> | ||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> | ||
package="io.flutter.plugins.imagepicker"> | ||
|
||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can someone point me towards documentation that talks about why we have either of these permissions declared? As mentioned here (see the first row in the table), no permissions are needed for accessing the cache directory. I think these permissions are over-reaching and it'd be nice to drop them. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, the same goes for any API level of course, not just 29+. I cannot actually find any evidence that the Therefore I would propose just removing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you tell me more about your issue with that platform exception? I put together this sample to prove you don't need that permission (in the sample I use the get content action successfully without it). If I can reproduce the issue it may help me understand why it's needed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry @BeMacized I just had another look at the code. You're running into that Exception because you likely removed the permission declaration from the manifest but didn't remove the request for it from the code, which isn't allowed. If you remove it in both places you should be able to fetch the image without issue. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I see! that makes things a lot more clear, thanks for the hint. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know I'm probably being a pest @BeMacized but it's worth noting the plugin also doesn't need to request the camera permission because it's using the FWIW, the reason I'm calling these all out is because it's nice for client apps to not request these permissions needlessly. It helps build trust with our users, so I'd love to see these go away if possible :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we could drop that one too that would indeed be excellent! I'll definitely take a look at it, although I can't guarantee it will also land together with this PR. |
||
<uses-permission | ||
android:name="android.permission.WRITE_EXTERNAL_STORAGE" | ||
android:maxSdkVersion="28" /> | ||
|
||
<application> | ||
<provider | ||
|
@@ -11,7 +14,7 @@ | |
android:grantUriPermissions="true"> | ||
<meta-data | ||
android:name="android.support.FILE_PROVIDER_PATHS" | ||
android:resource="@xml/flutter_image_picker_file_paths"/> | ||
android:resource="@xml/flutter_image_picker_file_paths" /> | ||
</provider> | ||
</application> | ||
</manifest> | ||
</manifest> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<paths> | ||
<external-path name="external_files" path="."/> | ||
</paths> | ||
<cache-path name="cached_files" path="."/> | ||
</paths> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,9 +4,12 @@ | |
|
||
package io.flutter.plugins.imagepicker; | ||
|
||
import static org.hamcrest.core.IsEqual.equalTo; | ||
import static org.junit.Assert.assertThat; | ||
import static org.junit.Assert.assertTrue; | ||
import static org.mockito.ArgumentMatchers.any; | ||
import static org.mockito.ArgumentMatchers.eq; | ||
import static org.mockito.Mockito.times; | ||
import static org.mockito.Mockito.verify; | ||
import static org.mockito.Mockito.verifyZeroInteractions; | ||
import static org.mockito.Mockito.when; | ||
|
@@ -15,6 +18,7 @@ | |
import android.app.Application; | ||
import io.flutter.plugin.common.MethodCall; | ||
import io.flutter.plugin.common.MethodChannel; | ||
import java.io.File; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import org.junit.Before; | ||
|
@@ -149,6 +153,20 @@ public void onConstructor_WhenContextTypeIsActivity_ShouldNotCrash() { | |
"No exception thrown when ImagePickerPlugin() ran with context instanceof Activity", true); | ||
} | ||
|
||
@Test | ||
public void constructDelegate_ShouldUseInternalCacheDirectory() { | ||
File mockDirectory = new File("/mockpath"); | ||
when(mockActivity.getCacheDir()).thenReturn(mockDirectory); | ||
|
||
ImagePickerDelegate delegate = plugin.constructDelegate(mockActivity); | ||
|
||
verify(mockActivity, times(1)).getCacheDir(); | ||
assertThat( | ||
"Delegate uses cache directory for storing camera captures", | ||
delegate.externalFilesDirectory, | ||
equalTo(mockDirectory)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be great if we also check (in another unit test) that calling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair point! A test for this has been added. |
||
} | ||
|
||
private MethodCall buildMethodCall(String method, final int source) { | ||
final Map<String, Object> arguments = new HashMap<>(); | ||
arguments.put("source", source); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
sdk=29 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am wondering if this should be considered as a breaking change. As the API itself doesn't change, but the locations where images from the camera are stored is changed to scoped storage instead of the Environment.DIRECTORY_PICTURES external file location.
Meaning it will be more difficult for other Apps to reach the images. @stuartmorgan or @cyanglaz can you possibly advice on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably better to err on the side of making it a breaking change since we don't know if people are relying on the location, even if it's not something that's guaranteed by the API.
@blasten any preference on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree the plugin never said that this was the case in the first place, but I'm inclined to think that given the nature of the issue, making it a major release sounds good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changelog and pubspec have been updated to show this as a breaking change.