Skip to content

Instantly share code, notes, and snippets.

@tentenponce
Last active March 4, 2019 04:39
Show Gist options
  • Save tentenponce/015c854fbadf7144c37020319e7f170c to your computer and use it in GitHub Desktop.
Save tentenponce/015c854fbadf7144c37020319e7f170c to your computer and use it in GitHub Desktop.
Handles permission and logic upon capturing or uploading an image or custom files.
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.support.annotation.RequiresApi;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AlertDialog;
import android.widget.Toast;
import com.itsgmobility.hrbenefits.BuildConfig;
import com.itsgmobility.hrbenefits.R;
import com.itsgmobility.hrbenefits.util.CameraUtil;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
public class ImageUploadHelper {
public static final int REQUEST_IMAGE_UPLOAD = 1;
public static final int REQUEST_FILE = 100;
public static final int REQUEST_CAMERA = 101;
private File mCapturedFile;
private Activity mActivity;
private Fragment mFragment;
private int mRequested;
private ArrayList<String> mMimeTypes = new ArrayList<>();
public ImageUploadHelper(Activity activity) {
mActivity = activity;
init();
}
public ImageUploadHelper(Fragment fragment) {
mFragment = fragment;
init();
}
public void init() {
/* default intent type is image, you can modify the intent type if you want to allow other extensions */
mMimeTypes.add("image/*");
}
public void showUploadDialog() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(getContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(getContext(), android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
requestPermissions();
return; // abort if no permission
}
}
final CharSequence[] options = {"Take Photo", "Choose From Files"};
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("Select Option");
builder.setItems(options, (dialog, item) -> {
dialog.dismiss();
if (options[item].equals("Take Photo")) {
mRequested = REQUEST_CAMERA;
showTakePhoto();
} else if (options[item].equals("Choose From Files")) {
mRequested = REQUEST_FILE;
showFileChooser();
}
});
builder.show();
}
private void showTakePhoto() {
try {
mCapturedFile = CameraUtil.getOutputMediaFile();
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri photoUri = FileProvider.getUriForFile(getContext(),
BuildConfig.APPLICATION_ID + ".provider",
mCapturedFile);
if (mCapturedFile != null) {
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(intent, REQUEST_CAMERA);
}
} catch (IOException e) {
Toast.makeText(getContext(), R.string.error_permission_storage, Toast.LENGTH_SHORT).show();
}
}
private void showFileChooser() {
//starts new mActivity to select file and return data
startActivityForResult(getFileChooserIntent(), REQUEST_FILE);
}
private Intent getFileChooserIntent() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
intent.setType(mMimeTypes.size() == 1 ? mMimeTypes.get(0) : "*/*");
if (mMimeTypes.size() > 0) {
intent.putExtra(Intent.EXTRA_MIME_TYPES, mMimeTypes);
}
} else {
StringBuilder mimeTypesStr = new StringBuilder();
for (String mimeType : mMimeTypes) {
mimeTypesStr.append(mimeType).append("|");
}
intent.setType(mimeTypesStr.substring(0, mimeTypesStr.length() - 1));
}
return intent;
}
public File getCapturedFile() {
if (mRequested == REQUEST_CAMERA) {
return mCapturedFile;
}
throw new InvalidRequestMethodException();
}
public Uri getCapturedFileAsUri() {
if (mRequested == REQUEST_CAMERA) {
return Uri.parse("file:" + mCapturedFile.getAbsolutePath());
}
throw new InvalidRequestMethodException();
}
public void addIntentType(String intentType) {
mMimeTypes.add(intentType);
}
private Context getContext() {
Context context = null;
if (mActivity != null) {
context = mActivity;
}
if (mFragment != null) {
context = mFragment.getContext();
}
return context;
}
private void startActivityForResult(Intent intent, int requestCode) {
if (mActivity != null) {
mActivity.startActivityForResult(intent, requestCode);
}
if (mFragment != null) {
mFragment.startActivityForResult(intent, requestCode);
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
private void requestPermissions() {
if (mActivity != null) {
mActivity.requestPermissions(
new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE
},
REQUEST_IMAGE_UPLOAD);
}
if (mFragment != null) {
mFragment.requestPermissions(
new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE
},
REQUEST_IMAGE_UPLOAD);
}
}
private class InvalidRequestMethodException extends RuntimeException {
InvalidRequestMethodException() {
super("Sorry, it seems that you haven't requested for camera. Please request camera first before getting the captured file.");
}
}
}
//==========================================================================//
/**
* Simple use case, capture or upload a photo
*/
void uploadImage() {
FileUploadHelper helper = new FileUploadHelper(this) // supports activity or fragment
//if you want to include other extension types, you can just include it by:
helper.addIntentType("application/pdf")
helper.showUploadDialog()
}
/**
* On activity or fragment, handle the `onActivityResult` method:
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK &&
requestCode == ImageUploadHelper.REQUEST_FILE) {
if (data == null) {
Toast.makeText(getContext(), R.string.error_no_image, Toast.LENGTH_SHORT).show();
return;
}
Uri selectedFileUri = data.getData();
String selectedFilePath = FileUtils.getPath(getContext(), selectedFileUri); // please refer to FileUtils.java
if (selectedFilePath == null || selectedFilePath.equals("")) {
Toast.makeText(getContext(), R.string.error_image_chooser, Toast.LENGTH_SHORT).show();
} else {
// mFile is the file from that was selected from your file manager
File mFile = new File(FileUtils.getPath(context, uri));
}
} else if (resultCode == Activity.RESULT_OK &&
requestCode == ImageUploadHelper.REQUEST_CAMERA) {
// mFile is the file from that was captured
File mFile = mImageUploadHelper.getCapturedFile();
}
}
/*
* Copyright (C) 2007-2008 OpenIntents.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.annotation.TargetApi;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.Log;
/**
* @author Peli
* @author paulburke (ipaulpro)
* @version 2013-12-11
* <p>
* Code Clean Up
* Tenten Ponce
* 2017-09-08
*/
public class FileUtils {
/**
* TAG for log messages.
*/
private static final String TAG = "FileUtils";
private static final boolean DEBUG = false; // Set to true to enable logging
private FileUtils() {
} //private constructor to enforce Singleton pattern
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is {@link LocalStorageProvider}.
* @author paulburke
*/
private static boolean isLocalStorageDocument(Uri uri) {
return LocalStorageProvider.AUTHORITY.equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
* @author paulburke
*/
private static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
* @author paulburke
*/
private static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
* @author paulburke
*/
private static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is Google Photos.
*/
private static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* @param context The context.
* @param uri The Uri to query.
* @param selection (Optional) Filter used in the query.
* @param selectionArgs (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path.
* @author paulburke
*/
private static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
if (DEBUG)
DatabaseUtils.dumpCursor(cursor);
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* Get a file path from a Uri. This will get the the path for Storage Access
* Framework Documents, as well as the _data field for the MediaStore and
* other file-based ContentProviders.<br>
* <br>
* Callers should check whether the path is local before assuming it
* represents a local file.
*
* @param context The context.
* @param uri The Uri to query.
* @author paulburke
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
public static String getPath(final Context context, final Uri uri) {
if (DEBUG)
Log.d(TAG + " File -",
"Authority: " + uri.getAuthority() +
", Fragment: " + uri.getFragment() +
", Port: " + uri.getPort() +
", Query: " + uri.getQuery() +
", Scheme: " + uri.getScheme() +
", Host: " + uri.getHost() +
", Segments: " + uri.getPathSegments().toString()
);
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// LocalStorageProvider
if (isLocalStorageDocument(uri)) {
// The path is the id
return DocumentsContract.getDocumentId(uri);
}
// ExternalStorageProvider
else if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment