Skip to content

Commit cd2277d

Browse files
authored
Merge pull request firebase#177 from samtstern/storage-edit
Make storage sample use file picker, not camera
2 parents f59a857 + c0ee6bc commit cd2277d

File tree

4 files changed

+67
-128
lines changed

4 files changed

+67
-128
lines changed

storage/app/build.gradle

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,40 +25,9 @@ configurations.all {
2525
resolutionStrategy.force 'com.android.support:support-annotations:24.2.1'
2626
}
2727

28-
// Based on: http://goo.gl/cuAayN
29-
// To run a test with permission granted:
30-
// ./gradlew :app:grantDebugPermissions :app:runDebugEspressoTests
31-
android.applicationVariants.all { variant ->
32-
def applicationId = variant.applicationId
33-
def adb = android.getAdbExe().toString()
34-
def variantName = variant.name.capitalize()
35-
def grantPermissionTask = tasks.create(name: "grant${variantName}Permissions", type: Exec) {
36-
"${adb} devices".execute().text.eachLine {
37-
if (it.endsWith("device")) {
38-
def device = it.split()[0]
39-
commandLine(adb, "-s", device, "shell", "pm", "grant", applicationId,
40-
"android.permission.WRITE_EXTERNAL_STORAGE")
41-
commandLine(adb, "-s", device, "shell", "pm", "grant", applicationId,
42-
"android.permission.READ_EXTERNAL_STORAGE")
43-
}
44-
}
45-
}
46-
47-
grantPermissionTask.dependsOn "install${variantName}"
48-
grantPermissionTask.dependsOn "install${variantName}AndroidTest"
49-
50-
def runEspressoTestsTask = tasks.create(name: "run${variantName}EspressoTests", type: Exec) {
51-
commandLine(adb, "shell", "am", "instrument", "-w", "-r", "-e", "debug", "false", "-e",
52-
"class", "${applicationId}.MainActivityTest",
53-
"${applicationId}.test/android.support.test.runner.AndroidJUnitRunner")
54-
}
55-
}
56-
5728
dependencies {
5829
compile 'com.android.support:appcompat-v7:24.2.1'
5930

60-
compile 'pub.devrel:easypermissions:0.2.0'
61-
6231
compile 'com.google.firebase:firebase-auth:9.8.0'
6332
compile 'com.google.firebase:firebase-storage:9.8.0'
6433

storage/app/src/androidTest/java/com/google/firebase/quickstart/firebasestorage/MainActivityTest.java

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,33 @@
11
package com.google.firebase.quickstart.firebasestorage;
22

3+
import android.Manifest;
34
import android.app.Activity;
45
import android.app.Instrumentation;
56
import android.content.Intent;
6-
import android.provider.MediaStore;
7-
import android.support.test.InstrumentationRegistry;
7+
import android.net.Uri;
8+
import android.os.Build;
89
import android.support.test.espresso.Espresso;
910
import android.support.test.espresso.NoMatchingViewException;
1011
import android.support.test.espresso.ViewInteraction;
1112
import android.support.test.espresso.intent.Intents;
1213
import android.support.test.rule.ActivityTestRule;
1314
import android.support.test.runner.AndroidJUnit4;
1415
import android.test.suitebuilder.annotation.LargeTest;
16+
import android.util.Log;
1517

1618
import org.hamcrest.Matcher;
1719
import org.junit.After;
1820
import org.junit.Before;
21+
import org.junit.BeforeClass;
1922
import org.junit.Rule;
2023
import org.junit.Test;
2124
import org.junit.runner.RunWith;
2225

26+
import java.io.File;
27+
import java.io.IOException;
28+
29+
import static android.support.test.InstrumentationRegistry.getInstrumentation;
30+
import static android.support.test.InstrumentationRegistry.getTargetContext;
2331
import static android.support.test.espresso.Espresso.onView;
2432
import static android.support.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu;
2533
import static android.support.test.espresso.action.ViewActions.click;
@@ -44,21 +52,25 @@ public class MainActivityTest {
4452
@Rule
4553
public ActivityTestRule<MainActivity> mActivityTestRule = new ActivityTestRule<>(MainActivity.class);
4654

55+
@BeforeClass
56+
public static void grantPermissions() {
57+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
58+
String packageName = getTargetContext().getPackageName();
59+
String testPackageName = packageName + ".test";
60+
61+
// Grant "WRITE_EXTERNAL_STORAGE"
62+
getInstrumentation().getUiAutomation().executeShellCommand(
63+
"pm grant " + packageName + Manifest.permission.WRITE_EXTERNAL_STORAGE);
64+
getInstrumentation().getUiAutomation().executeShellCommand(
65+
"pm grant " + testPackageName + Manifest.permission.WRITE_EXTERNAL_STORAGE);
66+
}
67+
}
68+
4769
@Before
4870
public void before() {
4971
// Initialize intents
5072
Intents.init();
5173

52-
// Create fake RESULT_OK Intent
53-
Intent intent = new Intent();
54-
intent.putExtra("is-espresso-test", true);
55-
Instrumentation.ActivityResult result = new Instrumentation.ActivityResult(
56-
Activity.RESULT_OK, intent);
57-
58-
// Intercept photo intent
59-
Matcher<Intent> pictureIntentMatch = allOf(hasAction(MediaStore.ACTION_IMAGE_CAPTURE));
60-
intending(pictureIntentMatch).respondWith(result);
61-
6274
// Idling resource
6375
mUploadIdlingResource = new ServiceIdlingResource(mActivityTestRule.getActivity(),
6476
MyUploadService.class);
@@ -78,17 +90,21 @@ public void after() {
7890

7991

8092
@Test
81-
public void uploadPhotoTest() {
93+
public void uploadPhotoTest() throws InterruptedException {
8294
// Log out to start
8395
logOutIfPossible();
8496

97+
// Create a temp file
98+
createTempFile();
99+
85100
// Click sign in
86101
ViewInteraction signInButton = onView(
87102
allOf(withId(R.id.button_sign_in), withText(R.string.sign_in_anonymously),
88103
isDisplayed()));
89104
signInButton.perform(click());
90105

91-
// TODO(samstern): what if permission has not been granted yet?
106+
// Wait for sign in
107+
Thread.sleep(5000);
92108

93109
// Click upload
94110
ViewInteraction uploadButton = onView(
@@ -110,17 +126,46 @@ public void uploadPhotoTest() {
110126
isDisplayed()));
111127
downloadButton.perform(click());
112128

129+
// Wait for download
130+
Thread.sleep(5000);
131+
113132
// Confirm that a success dialog appears
114133
onView(withText(R.string.success)).inRoot(isDialog())
115134
.check(matches(isDisplayed()));
116135
}
117136

137+
/**
138+
* Create a file to be selected by tests.
139+
*/
140+
private void createTempFile() {
141+
// Create fake RESULT_OK Intent
142+
Intent intent = new Intent();
143+
intent.putExtra("is-espresso-test", true);
144+
145+
// Create a temporary file for the result of the intent
146+
File external = mActivityTestRule.getActivity().getExternalFilesDir(null);
147+
File imageFile = new File(external, "tmp.jpg");
148+
try {
149+
imageFile.createNewFile();
150+
} catch (IOException e) {
151+
Log.e(TAG, "createNewFile", e);
152+
}
153+
intent.setData(Uri.fromFile(imageFile));
154+
155+
Instrumentation.ActivityResult result = new Instrumentation.ActivityResult(
156+
Activity.RESULT_OK, intent);
157+
158+
// Intercept photo intent
159+
Matcher<Intent> pictureIntentMatch = allOf(hasAction(Intent.ACTION_GET_CONTENT));
160+
intending(pictureIntentMatch).respondWith(result);
161+
}
162+
118163
/**
119164
* Click the 'Log Out' overflow menu if it exists (which would mean we're signed in).
120165
*/
121166
private void logOutIfPossible() {
122167
try {
123-
openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getTargetContext());
168+
openActionBarOverflowOrOptionsMenu(getTargetContext());
124169
onView(withText(R.string.log_out)).perform(click());
125170
} catch (NoMatchingViewException e) {
126171
// Ignore exception since we only want to do this operation if it's easy.

storage/app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
33
package="com.google.firebase.quickstart.firebasestorage">
44

5-
<!--
6-
This permission is not required for Firebase Storage and is only used to read
7-
files from the camera and upload them to Firebase Storage as a demonstration.
8-
-->
5+
<!-- Used only for testing purposes, not required for Firebase Storage -->
96
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
107

118
<application
@@ -32,20 +29,6 @@
3229
android:name=".MyUploadService"
3330
android:exported="false" />
3431

35-
<!--
36-
Android N SDK has new restrictions around sharing file:// URIs
37-
https://developer.android.com/reference/android/support/v4/content/FileProvider.html#ProviderDefinition
38-
-->
39-
<provider
40-
android:name="android.support.v4.content.FileProvider"
41-
android:authorities="com.google.firebase.quickstart.firebasestorage.fileprovider"
42-
android:exported="false"
43-
android:grantUriPermissions="true">
44-
<meta-data
45-
android:name="android.support.FILE_PROVIDER_PATHS"
46-
android:resource="@xml/file_paths" />
47-
</provider>
48-
4932
</application>
5033

5134
</manifest>

storage/app/src/main/java/com/google/firebase/quickstart/firebasestorage/MainActivity.java

Lines changed: 6 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,13 @@
1616

1717
package com.google.firebase.quickstart.firebasestorage;
1818

19-
import android.Manifest;
2019
import android.app.ProgressDialog;
2120
import android.content.BroadcastReceiver;
2221
import android.content.Context;
2322
import android.content.Intent;
24-
import android.content.pm.PackageManager;
25-
import android.content.pm.ResolveInfo;
2623
import android.net.Uri;
2724
import android.os.Bundle;
28-
import android.os.Environment;
29-
import android.provider.MediaStore;
3025
import android.support.annotation.NonNull;
31-
import android.support.v4.content.FileProvider;
3226
import android.support.v4.content.LocalBroadcastManager;
3327
import android.support.v7.app.AlertDialog;
3428
import android.support.v7.app.AppCompatActivity;
@@ -45,14 +39,7 @@
4539
import com.google.firebase.auth.FirebaseAuth;
4640
import com.google.firebase.auth.FirebaseUser;
4741

48-
import java.io.File;
49-
import java.io.IOException;
50-
import java.util.List;
5142
import java.util.Locale;
52-
import java.util.UUID;
53-
54-
import pub.devrel.easypermissions.AfterPermissionGranted;
55-
import pub.devrel.easypermissions.EasyPermissions;
5643

5744
/**
5845
* Activity to upload and download photos from Firebase Storage.
@@ -65,7 +52,6 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
6552
private static final String TAG = "Storage#MainActivity";
6653

6754
private static final int RC_TAKE_PICTURE = 101;
68-
private static final int RC_STORAGE_PERMS = 102;
6955

7056
private static final String KEY_FILE_URI = "key_file_uri";
7157
private static final String KEY_DOWNLOAD_URL = "key_download_url";
@@ -171,6 +157,8 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
171157
Log.d(TAG, "onActivityResult:" + requestCode + ":" + resultCode + ":" + data);
172158
if (requestCode == RC_TAKE_PICTURE) {
173159
if (resultCode == RESULT_OK) {
160+
mFileUri = data.getData();
161+
174162
if (mFileUri != null) {
175163
uploadFromUri(mFileUri);
176164
} else {
@@ -216,53 +204,13 @@ private void beginDownload() {
216204
showProgressDialog();
217205
}
218206

219-
220-
@AfterPermissionGranted(RC_STORAGE_PERMS)
221207
private void launchCamera() {
222208
Log.d(TAG, "launchCamera");
223209

224-
// Check that we have permission to read images from external storage.
225-
String perm = Manifest.permission.WRITE_EXTERNAL_STORAGE;
226-
if (!EasyPermissions.hasPermissions(this, perm)) {
227-
EasyPermissions.requestPermissions(this, getString(R.string.rationale_storage),
228-
RC_STORAGE_PERMS, perm);
229-
return;
230-
}
231-
232-
// Choose file storage ___location, must be listed in res/xml/file_paths.xml
233-
File dir = new File(Environment.getExternalStorageDirectory() + "/photos");
234-
File file = new File(dir, UUID.randomUUID().toString() + ".jpg");
235-
try {
236-
// Create directory if it does not exist.
237-
if (!dir.exists()) {
238-
dir.mkdir();
239-
}
240-
boolean created = file.createNewFile();
241-
Log.d(TAG, "file.createNewFile:" + file.getAbsolutePath() + ":" + created);
242-
} catch (IOException e) {
243-
Log.e(TAG, "file.createNewFile" + file.getAbsolutePath() + ":FAILED", e);
244-
}
245-
246-
// Create content:// URI for file, required since Android N
247-
// See: https://developer.android.com/reference/android/support/v4/content/FileProvider.html
248-
mFileUri = FileProvider.getUriForFile(this,
249-
"com.google.firebase.quickstart.firebasestorage.fileprovider", file);
250-
251-
// Create and launch the intent
252-
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
253-
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mFileUri);
254-
255-
// Grant permission to camera (this is required on KitKat and below)
256-
List<ResolveInfo> resolveInfos = getPackageManager()
257-
.queryIntentActivities(takePictureIntent, PackageManager.MATCH_DEFAULT_ONLY);
258-
for (ResolveInfo resolveInfo : resolveInfos) {
259-
String packageName = resolveInfo.activityInfo.packageName;
260-
grantUriPermission(packageName, mFileUri,
261-
Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
262-
}
263-
264-
// Start picture-taking intent
265-
startActivityForResult(takePictureIntent, RC_TAKE_PICTURE);
210+
// Pick an image from storage
211+
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
212+
intent.setType("image/*");
213+
startActivityForResult(intent, RC_TAKE_PICTURE);
266214
}
267215

268216
private void signInAnonymously() {
@@ -370,10 +318,4 @@ public void onClick(View v) {
370318
beginDownload();
371319
}
372320
}
373-
374-
@Override
375-
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
376-
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
377-
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
378-
}
379321
}

0 commit comments

Comments
 (0)