Last active
March 4, 2019 04:39
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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."); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//==========================================================================// | |
/** | |
* 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(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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