From f089dc0fd6fbe936ea0fbf6404655c9e0b2c6269 Mon Sep 17 00:00:00 2001 From: micabkyle Date: Tue, 27 Jun 2017 18:40:05 +0800 Subject: [PATCH 1/2] Updating for Nougat --- app/build.gradle | 8 ++++---- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- multi-image-selector/build.gradle | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 6536c30..f81392c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,13 +1,13 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 23 - buildToolsVersion "23.0.3" + compileSdkVersion 25 + buildToolsVersion '25.0.3' defaultConfig { applicationId "me.nereo.multiimageselector" minSdkVersion 12 - targetSdkVersion 23 + targetSdkVersion 25 versionCode 1 versionName "1.0" } @@ -21,6 +21,6 @@ android { dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') - compile 'com.android.support:appcompat-v7:23.4.0' + compile 'com.android.support:appcompat-v7:25.3.1' compile project(':multi-image-selector') } diff --git a/build.gradle b/build.gradle index f6e9073..ea98e44 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.0' + classpath 'com.android.tools.build:gradle:2.3.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7af1915..29e37c0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed May 18 11:49:16 CST 2016 +#Tue Jun 27 18:33:07 PHT 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip diff --git a/multi-image-selector/build.gradle b/multi-image-selector/build.gradle index dba9a97..b8289c3 100644 --- a/multi-image-selector/build.gradle +++ b/multi-image-selector/build.gradle @@ -1,12 +1,12 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 23 - buildToolsVersion "23.0.3" + compileSdkVersion 25 + buildToolsVersion '25.0.3' defaultConfig { minSdkVersion 12 - targetSdkVersion 23 + targetSdkVersion 25 versionCode 1 versionName "1.1" } @@ -22,6 +22,6 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:23.4.0' + compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.squareup.picasso:picasso:2.4.0' } From e781d9bf33704a97e3da461c2d74aad5e29cada9 Mon Sep 17 00:00:00 2001 From: micabkyle Date: Tue, 27 Jun 2017 18:58:12 +0800 Subject: [PATCH 2/2] Added FileProvider for N --- .../src/main/AndroidManifest.xml | 10 ++ .../MultiImageSelectorActivity.java | 60 +++++--- .../MultiImageSelectorFragment.java | 129 +++++++++++------- .../src/main/res/xml/mis_provider_paths.xml | 4 + 4 files changed, 128 insertions(+), 75 deletions(-) create mode 100644 multi-image-selector/src/main/res/xml/mis_provider_paths.xml diff --git a/multi-image-selector/src/main/AndroidManifest.xml b/multi-image-selector/src/main/AndroidManifest.xml index 7fd4a3a..a700bbc 100644 --- a/multi-image-selector/src/main/AndroidManifest.xml +++ b/multi-image-selector/src/main/AndroidManifest.xml @@ -10,6 +10,16 @@ android:configChanges="orientation|screenSize" android:name="me.nereo.multi_image_selector.MultiImageSelectorActivity" /> + + + + diff --git a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorActivity.java b/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorActivity.java index 26905ca..d7759d0 100644 --- a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorActivity.java +++ b/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorActivity.java @@ -6,6 +6,7 @@ import android.os.Build; import android.os.Bundle; import android.support.v4.app.Fragment; +import android.support.v4.content.FileProvider; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; @@ -23,22 +24,32 @@ * Updated by nereo on 2016/5/18. */ public class MultiImageSelectorActivity extends AppCompatActivity - implements MultiImageSelectorFragment.Callback{ + implements MultiImageSelectorFragment.Callback { // Single choice public static final int MODE_SINGLE = 0; // Multi choice public static final int MODE_MULTI = 1; - /** Max image size,int,{@link #DEFAULT_IMAGE_SIZE} by default */ + /** + * Max image size,int,{@link #DEFAULT_IMAGE_SIZE} by default + */ public static final String EXTRA_SELECT_COUNT = "max_select_count"; - /** Select mode,{@link #MODE_MULTI} by default */ + /** + * Select mode,{@link #MODE_MULTI} by default + */ public static final String EXTRA_SELECT_MODE = "select_count_mode"; - /** Whether show camera,true by default */ + /** + * Whether show camera,true by default + */ public static final String EXTRA_SHOW_CAMERA = "show_camera"; - /** Result data set,ArrayList<String>*/ + /** + * Result data set,ArrayList<String> + */ public static final String EXTRA_RESULT = "select_result"; - /** Original data set */ + /** + * Original data set + */ public static final String EXTRA_DEFAULT_SELECTED_LIST = "default_list"; // Default image size private static final int DEFAULT_IMAGE_SIZE = 9; @@ -58,7 +69,7 @@ protected void onCreate(Bundle savedInstanceState) { } Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); - if(toolbar != null){ + if (toolbar != null) { setSupportActionBar(toolbar); } @@ -71,33 +82,33 @@ protected void onCreate(Bundle savedInstanceState) { mDefaultCount = intent.getIntExtra(EXTRA_SELECT_COUNT, DEFAULT_IMAGE_SIZE); final int mode = intent.getIntExtra(EXTRA_SELECT_MODE, MODE_MULTI); final boolean isShow = intent.getBooleanExtra(EXTRA_SHOW_CAMERA, true); - if(mode == MODE_MULTI && intent.hasExtra(EXTRA_DEFAULT_SELECTED_LIST)) { + if (mode == MODE_MULTI && intent.hasExtra(EXTRA_DEFAULT_SELECTED_LIST)) { resultList = intent.getStringArrayListExtra(EXTRA_DEFAULT_SELECTED_LIST); } mSubmitButton = (Button) findViewById(R.id.commit); - if(mode == MODE_MULTI){ + if (mode == MODE_MULTI) { updateDoneText(resultList); mSubmitButton.setVisibility(View.VISIBLE); mSubmitButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - if(resultList != null && resultList.size() >0){ + if (resultList != null && resultList.size() > 0) { // Notify success Intent data = new Intent(); data.putStringArrayListExtra(EXTRA_RESULT, resultList); setResult(RESULT_OK, data); - }else{ + } else { setResult(RESULT_CANCELED); } finish(); } }); - }else{ + } else { mSubmitButton.setVisibility(View.GONE); } - if(savedInstanceState == null){ + if (savedInstanceState == null) { Bundle bundle = new Bundle(); bundle.putInt(MultiImageSelectorFragment.EXTRA_SELECT_COUNT, mDefaultCount); bundle.putInt(MultiImageSelectorFragment.EXTRA_SELECT_MODE, mode); @@ -108,7 +119,6 @@ public void onClick(View view) { .add(R.id.image_grid, Fragment.instantiate(this, MultiImageSelectorFragment.class.getName(), bundle)) .commit(); } - } @Override @@ -124,14 +134,15 @@ public boolean onOptionsItemSelected(MenuItem item) { /** * Update done button by select image data + * * @param resultList selected image data */ - private void updateDoneText(ArrayList resultList){ + private void updateDoneText(ArrayList resultList) { int size = 0; - if(resultList == null || resultList.size()<=0){ + if (resultList == null || resultList.size() <= 0) { mSubmitButton.setText(R.string.mis_action_done); mSubmitButton.setEnabled(false); - }else{ + } else { size = resultList.size(); mSubmitButton.setEnabled(true); } @@ -150,7 +161,7 @@ public void onSingleImageSelected(String path) { @Override public void onImageSelected(String path) { - if(!resultList.contains(path)) { + if (!resultList.contains(path)) { resultList.add(path); } updateDoneText(resultList); @@ -158,7 +169,7 @@ public void onImageSelected(String path) { @Override public void onImageUnselected(String path) { - if(resultList.contains(path)){ + if (resultList.contains(path)) { resultList.remove(path); } updateDoneText(resultList); @@ -166,9 +177,14 @@ public void onImageUnselected(String path) { @Override public void onCameraShot(File imageFile) { - if(imageFile != null) { + if (imageFile != null) { // notify system the image has change - sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(imageFile))); + + final Uri fileUri = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? + FileProvider.getUriForFile(this, getPackageName().concat(".provider"), imageFile) + : Uri.fromFile(imageFile); + + sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, fileUri)); Intent data = new Intent(); resultList.add(imageFile.getAbsolutePath()); @@ -177,4 +193,4 @@ public void onCameraShot(File imageFile) { finish(); } } -} +} \ No newline at end of file diff --git a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorFragment.java b/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorFragment.java index 4c068c6..ae9cf27 100644 --- a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorFragment.java +++ b/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorFragment.java @@ -12,6 +12,7 @@ import android.graphics.Point; import android.graphics.drawable.ColorDrawable; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.provider.MediaStore; @@ -21,6 +22,7 @@ import android.support.v4.app.LoaderManager; import android.support.v4.content.ContextCompat; import android.support.v4.content.CursorLoader; +import android.support.v4.content.FileProvider; import android.support.v4.content.Loader; import android.support.v7.app.AlertDialog; import android.support.v7.widget.ListPopupWindow; @@ -67,13 +69,21 @@ public class MultiImageSelectorFragment extends Fragment { // Multi choice public static final int MODE_MULTI = 1; - /** Max image size,int,*/ + /** + * Max image size,int, + */ public static final String EXTRA_SELECT_COUNT = "max_select_count"; - /** Select mode,{@link #MODE_MULTI} by default */ + /** + * Select mode,{@link #MODE_MULTI} by default + */ public static final String EXTRA_SELECT_MODE = "select_count_mode"; - /** Whether show camera,true by default */ + /** + * Whether show camera,true by default + */ public static final String EXTRA_SHOW_CAMERA = "show_camera"; - /** Original data set */ + /** + * Original data set + */ public static final String EXTRA_DEFAULT_SELECTED_LIST = "default_list"; // loaders @@ -105,7 +115,7 @@ public void onAttach(Context context) { super.onAttach(context); try { mCallback = (Callback) getActivity(); - }catch (ClassCastException e){ + } catch (ClassCastException e) { throw new ClassCastException("The Activity must implement MultiImageSelectorFragment.Callback interface..."); } } @@ -120,9 +130,9 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); final int mode = selectMode(); - if(mode == MODE_MULTI) { + if (mode == MODE_MULTI) { ArrayList tmp = getArguments().getStringArrayList(EXTRA_DEFAULT_SELECTED_LIST); - if(tmp != null && tmp.size()>0) { + if (tmp != null && tmp.size() > 0) { resultList = tmp; } } @@ -137,7 +147,7 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { @Override public void onClick(View view) { - if(mFolderPopupWindow == null){ + if (mFolderPopupWindow == null) { createPopupFolderList(); } @@ -195,7 +205,7 @@ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCoun private void createPopupFolderList() { Point point = ScreenUtils.getScreenSize(getActivity()); int width = point.x; - int height = (int) (point.y * (4.5f/8.0f)); + int height = (int) (point.y * (4.5f / 8.0f)); mFolderPopupWindow = new ListPopupWindow(getActivity()); mFolderPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.WHITE)); mFolderPopupWindow.setAdapter(mFolderAdapter); @@ -270,18 +280,18 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - if(requestCode == REQUEST_CAMERA){ - if(resultCode == Activity.RESULT_OK) { + if (requestCode == REQUEST_CAMERA) { + if (resultCode == Activity.RESULT_OK) { if (mTmpFile != null) { if (mCallback != null) { mCallback.onCameraShot(mTmpFile); } } - }else{ + } else { // delete tmp file - while (mTmpFile != null && mTmpFile.exists()){ + while (mTmpFile != null && mTmpFile.exists()) { boolean success = mTmpFile.delete(); - if(success){ + if (success) { mTmpFile = null; } } @@ -291,8 +301,8 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { @Override public void onConfigurationChanged(Configuration newConfig) { - if(mFolderPopupWindow != null){ - if(mFolderPopupWindow.isShowing()){ + if (mFolderPopupWindow != null) { + if (mFolderPopupWindow.isShowing()) { mFolderPopupWindow.dismiss(); } } @@ -303,12 +313,12 @@ public void onConfigurationChanged(Configuration newConfig) { * Open camera */ private void showCameraAction() { - if(ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) - != PackageManager.PERMISSION_GRANTED){ + if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, getString(R.string.mis_permission_rationale_write_storage), REQUEST_STORAGE_WRITE_ACCESS_PERMISSION); - }else { + } else { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (intent.resolveActivity(getActivity().getPackageManager()) != null) { try { @@ -317,8 +327,15 @@ private void showCameraAction() { e.printStackTrace(); } if (mTmpFile != null && mTmpFile.exists()) { - intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTmpFile)); + + final Uri fileUri = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? + FileProvider.getUriForFile(getContext(), getContext().getPackageName().concat(".provider"), mTmpFile) + : Uri.fromFile(mTmpFile); + + intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); startActivityForResult(intent, REQUEST_CAMERA); + + } else { Toast.makeText(getActivity(), R.string.mis_error_image_not_exist, Toast.LENGTH_SHORT).show(); } @@ -328,8 +345,8 @@ private void showCameraAction() { } } - private void requestPermission(final String permission, String rationale, final int requestCode){ - if(shouldShowRequestPermissionRationale(permission)){ + private void requestPermission(final String permission, String rationale, final int requestCode) { + if (shouldShowRequestPermissionRationale(permission)) { new AlertDialog.Builder(getContext()) .setTitle(R.string.mis_permission_dialog_title) .setMessage(rationale) @@ -341,15 +358,15 @@ public void onClick(DialogInterface dialog, int which) { }) .setNegativeButton(R.string.mis_permission_dialog_cancel, null) .create().show(); - }else{ + } else { requestPermissions(new String[]{permission}, requestCode); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - if(requestCode == REQUEST_STORAGE_WRITE_ACCESS_PERMISSION){ - if(grantResults[0] == PackageManager.PERMISSION_GRANTED){ + if (requestCode == REQUEST_STORAGE_WRITE_ACCESS_PERMISSION) { + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { showCameraAction(); } } else { @@ -359,18 +376,19 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis /** * notify callback + * * @param image image data */ private void selectImageFromGrid(Image image, int mode) { - if(image != null) { - if(mode == MODE_MULTI) { + if (image != null) { + if (mode == MODE_MULTI) { if (resultList.contains(image.path)) { resultList.remove(image.path); if (mCallback != null) { mCallback.onImageUnselected(image.path); } } else { - if(selectImageCount() == resultList.size()){ + if (selectImageCount() == resultList.size()) { Toast.makeText(getActivity(), R.string.mis_msg_amount_limit, Toast.LENGTH_SHORT).show(); return; } @@ -380,8 +398,8 @@ private void selectImageFromGrid(Image image, int mode) { } } mImageAdapter.select(image); - }else if(mode == MODE_SINGLE){ - if(mCallback != null){ + } else if (mode == MODE_SINGLE) { + if (mCallback != null) { mCallback.onSingleImageSelected(image.path); } } @@ -396,27 +414,27 @@ private void selectImageFromGrid(Image image, int mode) { MediaStore.Images.Media.DATE_ADDED, MediaStore.Images.Media.MIME_TYPE, MediaStore.Images.Media.SIZE, - MediaStore.Images.Media._ID }; + MediaStore.Images.Media._ID}; @Override public Loader onCreateLoader(int id, Bundle args) { CursorLoader cursorLoader = null; - if(id == LOADER_ALL) { + if (id == LOADER_ALL) { cursorLoader = new CursorLoader(getActivity(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION, - IMAGE_PROJECTION[4]+">0 AND "+IMAGE_PROJECTION[3]+"=? OR "+IMAGE_PROJECTION[3]+"=? ", + IMAGE_PROJECTION[4] + ">0 AND " + IMAGE_PROJECTION[3] + "=? OR " + IMAGE_PROJECTION[3] + "=? ", new String[]{"image/jpeg", "image/png"}, IMAGE_PROJECTION[2] + " DESC"); - }else if(id == LOADER_CATEGORY){ + } else if (id == LOADER_CATEGORY) { cursorLoader = new CursorLoader(getActivity(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION, - IMAGE_PROJECTION[4]+">0 AND "+IMAGE_PROJECTION[0]+" like '%"+args.getString("path")+"%'", + IMAGE_PROJECTION[4] + ">0 AND " + IMAGE_PROJECTION[0] + " like '%" + args.getString("path") + "%'", null, IMAGE_PROJECTION[2] + " DESC"); } return cursorLoader; } - private boolean fileExist(String path){ - if(!TextUtils.isEmpty(path)){ + private boolean fileExist(String path) { + if (!TextUtils.isEmpty(path)) { return new File(path).exists(); } return false; @@ -428,23 +446,25 @@ public void onLoadFinished(Loader loader, Cursor data) { if (data.getCount() > 0) { List images = new ArrayList<>(); data.moveToFirst(); - do{ + do { String path = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[0])); String name = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[1])); long dateTime = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[2])); - if(!fileExist(path)){continue;} + if (!fileExist(path)) { + continue; + } Image image = null; if (!TextUtils.isEmpty(name)) { image = new Image(path, name, dateTime); images.add(image); } - if( !hasFolderGened ) { + if (!hasFolderGened) { // get all folder data File folderFile = new File(path).getParentFile(); - if(folderFile != null && folderFile.exists()){ + if (folderFile != null && folderFile.exists()) { String fp = folderFile.getAbsolutePath(); Folder f = getFolderByPath(fp); - if(f == null){ + if (f == null) { Folder folder = new Folder(); folder.name = folderFile.getName(); folder.path = fp; @@ -453,19 +473,19 @@ public void onLoadFinished(Loader loader, Cursor data) { imageList.add(image); folder.images = imageList; mResultFolder.add(folder); - }else { + } else { f.images.add(image); } } } - }while(data.moveToNext()); + } while (data.moveToNext()); mImageAdapter.setData(images); - if(resultList != null && resultList.size()>0){ + if (resultList != null && resultList.size() > 0) { mImageAdapter.setDefaultSelected(resultList); } - if(!hasFolderGened) { + if (!hasFolderGened) { mFolderAdapter.setData(mResultFolder); hasFolderGened = true; } @@ -479,10 +499,10 @@ public void onLoaderReset(Loader loader) { } }; - private Folder getFolderByPath(String path){ - if(mResultFolder != null){ + private Folder getFolderByPath(String path) { + if (mResultFolder != null) { for (Folder folder : mResultFolder) { - if(TextUtils.equals(folder.path, path)){ + if (TextUtils.equals(folder.path, path)) { return folder; } } @@ -490,25 +510,28 @@ private Folder getFolderByPath(String path){ return null; } - private boolean showCamera(){ + private boolean showCamera() { return getArguments() == null || getArguments().getBoolean(EXTRA_SHOW_CAMERA, true); } - private int selectMode(){ + private int selectMode() { return getArguments() == null ? MODE_MULTI : getArguments().getInt(EXTRA_SELECT_MODE); } - private int selectImageCount(){ + private int selectImageCount() { return getArguments() == null ? 9 : getArguments().getInt(EXTRA_SELECT_COUNT); } /** * Callback for host activity */ - public interface Callback{ + public interface Callback { void onSingleImageSelected(String path); + void onImageSelected(String path); + void onImageUnselected(String path); + void onCameraShot(File imageFile); } } diff --git a/multi-image-selector/src/main/res/xml/mis_provider_paths.xml b/multi-image-selector/src/main/res/xml/mis_provider_paths.xml new file mode 100644 index 0000000..ffa74ab --- /dev/null +++ b/multi-image-selector/src/main/res/xml/mis_provider_paths.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file