├── app
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── quiro
│ │ └── fileproviderexample
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── quiro
│ │ │ └── fileproviderexample
│ │ │ ├── MainActivity.java
│ │ │ └── PermissionManager.java
│ └── res
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ ├── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ │ └── xml
│ │ └── file_provider_paths.xml
│ └── test
│ └── java
│ └── com
│ └── quiro
│ └── fileproviderexample
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ └── gradle-wrapper.properties
└── settings.gradle
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.2"
6 | defaultConfig {
7 | applicationId "com.quiro.fileproviderexample"
8 | minSdkVersion 17
9 | targetSdkVersion 25
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
25 | exclude group: 'com.android.support', module: 'support-annotations'
26 | })
27 | compile 'com.android.support:appcompat-v7:25.1.1'
28 | testCompile 'junit:junit:4.12'
29 | }
30 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/lorenzo/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/quiro/fileproviderexample/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.quiro.fileproviderexample;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.quiro.fileproviderexample", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
11 |
12 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
32 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/quiro/fileproviderexample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.quiro.fileproviderexample;
2 |
3 | import android.app.Activity;
4 | import android.content.ClipData;
5 | import android.content.Intent;
6 | import android.graphics.Bitmap;
7 | import android.graphics.BitmapFactory;
8 | import android.net.Uri;
9 | import android.os.Build;
10 | import android.os.Bundle;
11 | import android.os.Environment;
12 | import android.provider.MediaStore;
13 | import android.support.v4.content.FileProvider;
14 | import android.support.v7.app.AppCompatActivity;
15 | import android.util.Log;
16 | import android.view.View;
17 | import android.widget.Button;
18 | import android.widget.ImageView;
19 |
20 | import java.io.File;
21 | import java.io.IOException;
22 | import java.text.SimpleDateFormat;
23 | import java.util.Date;
24 |
25 | public class MainActivity extends AppCompatActivity {
26 |
27 | private static final int PHOTO_REQUEST_CODE = 102;
28 | private String path;
29 | private ImageView pictureView;
30 |
31 | @Override
32 | protected void onCreate(Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 | setContentView(R.layout.activity_main);
35 |
36 | Button takePhotoButton = (Button) findViewById(R.id.takePhotoButton);
37 | pictureView = (ImageView) findViewById(R.id.pictureView);
38 |
39 | final PermissionManager permissionManager = new PermissionManager();
40 |
41 | takePhotoButton.setOnClickListener(new View.OnClickListener() {
42 | @Override
43 | public void onClick(View v) {
44 | if (permissionManager.userHasPermission(MainActivity.this)) {
45 | takePicture();
46 | } else {
47 | permissionManager.requestPermission(MainActivity.this);
48 | }
49 | }
50 | });
51 | }
52 |
53 | public void onActivityResult(int requestCode, int resultCode, Intent data) {
54 | if (requestCode == PHOTO_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
55 | Bitmap source = BitmapFactory.decodeFile(path, provideCompressionBitmapFactoryOptions());
56 | pictureView.setImageBitmap(source);
57 | }
58 | }
59 |
60 | private void takePicture() {
61 | Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
62 | if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
63 | Uri photoURI = null;
64 | try {
65 | File photoFile = createImageFileWith();
66 | path = photoFile.getAbsolutePath();
67 | photoURI = FileProvider.getUriForFile(MainActivity.this,
68 | getString(R.string.file_provider_authority),
69 | photoFile);
70 |
71 | } catch (IOException ex) {
72 | Log.e("TakePicture", ex.getMessage());
73 | }
74 | takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
75 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {
76 | takePictureIntent.setClipData(ClipData.newRawUri("", photoURI));
77 | takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
78 | }
79 | startActivityForResult(takePictureIntent, PHOTO_REQUEST_CODE);
80 | }
81 | }
82 |
83 | private static BitmapFactory.Options provideCompressionBitmapFactoryOptions() {
84 | BitmapFactory.Options opt = new BitmapFactory.Options();
85 | opt.inJustDecodeBounds = false;
86 | opt.inPreferredConfig = Bitmap.Config.RGB_565;
87 | return opt;
88 | }
89 |
90 | public File createImageFileWith() throws IOException {
91 | final String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
92 | final String imageFileName = "JPEG_" + timestamp;
93 | File storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "pics");
94 | storageDir.mkdirs();
95 | return File.createTempFile(imageFileName, ".jpg", storageDir);
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/app/src/main/java/com/quiro/fileproviderexample/PermissionManager.java:
--------------------------------------------------------------------------------
1 | package com.quiro.fileproviderexample;
2 |
3 | import android.Manifest;
4 | import android.app.Activity;
5 | import android.content.Context;
6 | import android.content.pm.PackageManager;
7 | import android.support.v4.app.ActivityCompat;
8 | import android.support.v4.content.ContextCompat;
9 |
10 | public class PermissionManager {
11 |
12 | public PermissionManager(){}
13 |
14 | private static final String[] PERMISSIONS = {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
15 | private static final int REQUEST_CODE = 101;
16 |
17 | public boolean userHasPermission(Context context){
18 | int permissionCheck = ContextCompat.checkSelfPermission(context, PERMISSIONS[0]);
19 | int permissionCheck2 = ContextCompat.checkSelfPermission(context, PERMISSIONS[1]);
20 | return permissionCheck == PackageManager.PERMISSION_GRANTED &&
21 | permissionCheck2 == PackageManager.PERMISSION_GRANTED;
22 | }
23 |
24 | public void requestPermission(Activity activity){
25 | ActivityCompat.requestPermissions(activity, PERMISSIONS, REQUEST_CODE);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
20 |
21 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/quiro91/FileProviderException/78a27fc78c5bf3646abfa38437e3481460a71c33/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/quiro91/FileProviderException/78a27fc78c5bf3646abfa38437e3481460a71c33/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/quiro91/FileProviderException/78a27fc78c5bf3646abfa38437e3481460a71c33/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/quiro91/FileProviderException/78a27fc78c5bf3646abfa38437e3481460a71c33/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/quiro91/FileProviderException/78a27fc78c5bf3646abfa38437e3481460a71c33/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | FileProviderExample
3 | Share it!
4 | Take a picture
5 |
6 | com.quiro.fileproviderexample.fileprovider
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/file_provider_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/app/src/test/java/com/quiro/fileproviderexample/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.quiro.fileproviderexample;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.2.3'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
7 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------