Skip to content

Commit

Permalink
Merge pull request Dhaval2404#27 from Dhaval2404/feature/v1.4
Browse files Browse the repository at this point in the history
Removed redundant CAMERA permission
  • Loading branch information
Dhaval2404 authored Sep 3, 2019
2 parents fbf8f9e + 2b118d4 commit 43b72d7
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 50 deletions.
21 changes: 8 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Almost 90% of the app that I have developed has Image upload feature. To simplif
```

```groovy
implementation 'com.github.dhaval2404:imagepicker:1.3'
implementation 'com.github.dhaval2404:imagepicker:1.4'
```

**If you are yet to Migrate on AndroidX, Use support build artifact:**
Expand Down Expand Up @@ -187,17 +187,7 @@ Almost 90% of the app that I have developed has Image upload feature. To simplif
<color name="ucrop_color_statusbar">@color/teal_700</color>
<color name="ucrop_color_widget_active">@color/teal_500</color>
</resources>
```
* You don't need to add any permissions to manifest, everything is merged automatically from library's manifest file. You can remove unnecessary permission by adding **tools:node="remove** tag.
```xml
<!--
If Not using Camera feature, Add following line in app manifest.
This will remove permission while manifest merge
-->
<uses-permission android:name="android.permission.CAMERA" tools:node="remove"/>
```
```
# 💥Compatibility
Expand All @@ -206,10 +196,15 @@ Almost 90% of the app that I have developed has Image upload feature. To simplif
# ✔️Changelog
### Version: 1.4
* Optimized Uri to File Conversion (Inspired by [Flutter ImagePicker](https://github.com/flutter/plugins/tree/master/packages/image_picker))
* Removed redundant CAMERA permission [#26](https://github.com/Dhaval2404/ImagePicker/issues/26) (Special Thanks to [PerrchicK](https://github.com/PerrchicK))
### Version: 1.3
* Sample app made compatible with Android Kitkat 4.4+ (API 19)
* Fixed Uri to File Conversion issue [#8](https://github.com/Dhaval2404/ImagePicker/issues/8)
* Fixed Uri to File Conversion issue [#8](https://github.com/Dhaval2404/ImagePicker/issues/8) (Special Thanks to [squeeish](https://github.com/squeeish))
### Version: 1.2
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
ext.kotlin_version = '1.3.21'
ext.kotlin_version = '1.3.41'
repositories {
google()
jcenter()
Expand Down
6 changes: 3 additions & 3 deletions imagepicker/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ android {
defaultConfig {
minSdkVersion 19
targetSdkVersion 28
versionCode 4
versionName "1.3"
versionCode 5
versionName "1.4"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down Expand Up @@ -69,7 +69,7 @@ ext {
siteUrl = 'https://github.com/Dhaval2404/ImagePicker/'
gitUrl = 'https://github.com/Dhaval2404/ImagePicker.git'

libraryVersion = '1.3'
libraryVersion = '1.4'
//If you are uploading new library try : gradlew install
//If you are updating existing library then execute: gradlew bintrayUpload
//In both the case don't forgot to put bintray credentials in local.properties file.
Expand Down
7 changes: 0 additions & 7 deletions imagepicker/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<!--
If Not using Camera feature, Add following line in app manifest.
This will remove permission while manifest merge
<uses-permission android:name="android.permission.CAMERA" tools:node="remove"/>
-->
<uses-permission android:name="android.permission.CAMERA" />

<application>

<activity android:name=".ImagePickerActivity"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ class ImagePickerActivity : FragmentActivity() {
mCameraProvider = CameraProvider(this)
mCameraProvider?.startIntent()
}
else->{
else -> {
Log.e(TAG, "Image provider can not be null")
//Something went Wrong! This case should never happen
// Something went Wrong! This case should never happen
setError(getString(R.string.error_task_cancelled))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ class CameraProvider(activity: ImagePickerActivity) : BaseProvider(activity) {
* Permission Require for Image Capture using Camera
*/
private val REQUIRED_PERMISSIONS = arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)

Expand Down Expand Up @@ -67,7 +66,7 @@ class CameraProvider(activity: ImagePickerActivity) : BaseProvider(activity) {
*/
private fun startCameraIntent() {
// Create and get empty file to store capture image content
mCameraFile = FileUtil.getCameraFile()
mCameraFile = FileUtil.getImageFile()

// Check if file exists
if (mCameraFile != null && mCameraFile!!.exists()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ class CompressionProvider(activity: ImagePickerActivity) : BaseProvider(activity
quality = 100
}

val compressFile: File? = FileUtil.getCameraFile()
val compressFile: File? = FileUtil.getImageFile()
return if (compressFile != null) {
ImageUtil.compressImage(
file, maxWidth.toFloat(), maxHeight.toFloat(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class CropProvider(activity: ImagePickerActivity) : BaseProvider(activity) {
*/
@Throws(IOException::class)
private fun cropImage(file: File) {
mCropImageFile = FileUtil.getCameraFile()
mCropImageFile = FileUtil.getImageFile()

if (mCropImageFile == null || !mCropImageFile!!.exists()) {
Log.e(TAG, "Failed to create crop image file")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,32 @@ import android.os.Build
import android.os.Environment
import android.provider.DocumentsContract
import android.provider.MediaStore
import java.io.IOException
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import java.io.OutputStream

/**
* https://gist.github.com/HBiSoft/15899990b8cd0723c3a894c1636550a8
* This file was taken from
* https://gist.github.com/HBiSoft/15899990b8cd0723c3a894c1636550a8
*
* This class acts as a drop in replacement for uCrop FileUtils class
* Later on it was modified from the below resource:
* https://raw.githubusercontent.com/iPaulPro/aFileChooser/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java
* https://raw.githubusercontent.com/iPaulPro/aFileChooser/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java
*/

object FileUriUtils {

fun getRealPath(context: Context, uri: Uri): String? {
var path = getPathFromLocalUri(context, uri)
if (path == null) {
path = getPathFromRemoteUri(context, uri)
}
return path
}

private fun getPathFromLocalUri(context: Context, uri: Uri): String? {

val isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT

Expand All @@ -40,13 +55,12 @@ object FileUriUtils {
// This is for checking SD Card
} else {
val path = "storage" + "/" + docId.replace(":", "/")
if(File(path).exists()){
if (File(path).exists()) {
path
}else{
"/storage/sdcard/"+split[1];
} else {
"/storage/sdcard/" + split[1]
}
}

} else if (isDownloadsDocument(uri)) {
val fileName = getFilePath(context, uri)
if (fileName != null) {
Expand Down Expand Up @@ -76,23 +90,24 @@ object FileUriUtils {
val selectionArgs = arrayOf(split[1])

return getDataColumn(context, contentUri, selection, selectionArgs)
}// MediaProvider
} // MediaProvider
// DownloadsProvider
} else if ("content".equals(uri.scheme!!, ignoreCase = true)) {

// Return the remote address
return if (isGooglePhotosUri(uri)) uri.lastPathSegment else getDataColumn(context, uri, null, null)

} else if ("file".equals(uri.scheme!!, ignoreCase = true)) {
return uri.path
}// File
} // File
// MediaStore (and general)

return null
}

private fun getDataColumn(
context: Context, uri: Uri?, selection: String?,
context: Context,
uri: Uri?,
selection: String?,
selectionArgs: Array<String>?
): String? {

Expand All @@ -106,13 +121,13 @@ object FileUriUtils {
val index = cursor.getColumnIndexOrThrow(column)
return cursor.getString(index)
}
} catch (ex: Exception) {
} finally {
cursor?.close()
}
return null
}


private fun getFilePath(context: Context, uri: Uri): String? {

var cursor: Cursor? = null
Expand All @@ -130,6 +145,62 @@ object FileUriUtils {
return null
}

private fun getPathFromRemoteUri(context: Context, uri: Uri): String? {
// The code below is why Java now has try-with-resources and the Files utility.
var file: File? = null
var inputStream: InputStream? = null
var outputStream: OutputStream? = null
var success = false
try {
val extension = getImageExtension(uri)
inputStream = context.contentResolver.openInputStream(uri)
file = FileUtil.getImageFile(context.cacheDir, extension)
outputStream = FileOutputStream(file)
if (inputStream != null) {
inputStream.copyTo(outputStream, bufferSize = 4 * 1024)
success = true
}
} catch (ignored: IOException) {
} finally {
try {
inputStream?.close()
} catch (ignored: IOException) {
}

try {
outputStream?.close()
} catch (ignored: IOException) {
// If closing the output stream fails, we cannot be sure that the
// target file was written in full. Flushing the stream merely moves
// the bytes into the OS, not necessarily to the file.
success = false
}
}
return if (success) file!!.path else null
}

/** @return extension of image with dot, or default .jpg if it none.
*/
private fun getImageExtension(uriImage: Uri): String {
var extension: String? = null

try {
val imagePath = uriImage.path
if (imagePath != null && imagePath.lastIndexOf(".") != -1) {
extension = imagePath.substring(imagePath.lastIndexOf(".") + 1)
}
} catch (e: Exception) {
extension = null
}

if (extension == null || extension.isEmpty()) {
// default extension for matches the previous behavior of the plugin
extension = "jpg"
}

return ".$extension"
}

/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,23 @@ import java.util.Date
object FileUtil {

/**
* Get Image File
*
* Default it will take Camera folder as it's directory
*
* @param dir File Folder in which file needs tobe created.
* @param extension String Image file extension.
* @return Return Empty file to store camera image.
* @throws IOException if permission denied of failed to create new file.
*/
fun getCameraFile(): File? {
fun getImageFile(dir: File? = null, extension: String? = null): File? {
try {
// Create an image file name
val imageFileName = "IMG_${getTimestamp()}.jpg"
val ext = extension ?: ".jpg"
val imageFileName = "IMG_${getTimestamp()}$ext"

// Create File Directory Object
val storageDir = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
"Camera"
)
val storageDir = dir ?: getCameraDirectory()

// Create Directory If not exist
if (!storageDir.exists()) storageDir.mkdirs()
Expand All @@ -48,6 +52,16 @@ object FileUtil {
}
}

/**
* Get Camera Image Directory
*
* @return File Camera Image Directory
*/
private fun getCameraDirectory(): File {
val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
return File(dir, "Camera")
}

/**
* Get Current Time in yyyyMMdd HHmmssSSS format
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.github.dhaval2404.imagepicker.util

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
Expand Down Expand Up @@ -79,4 +80,8 @@ object IntentUtils {

return intent
}

fun isCameraHardwareAvailable(context: Context): Boolean {
return context.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)
}
}
9 changes: 6 additions & 3 deletions sample/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ android {
applicationId "com.github.dhaval2404.imagepicker.sample"
minSdkVersion 19
targetSdkVersion 28
versionCode 4
versionName "1.3"
versionCode 5
versionName "1.4"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
}
Expand All @@ -38,7 +38,7 @@ dependencies {

implementation 'androidx.core:core-ktx:1.0.2'
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'com.google.android.material:material:1.1.0-alpha08'
implementation 'com.google.android.material:material:1.1.0-alpha09'
implementation 'com.github.florent37:inline-activity-result-kotlin:1.0.1'

testImplementation 'junit:junit:4.12'
Expand All @@ -48,5 +48,8 @@ dependencies {
//Image Loading Lib
implementation 'com.github.bumptech.glide:glide:4.9.0'

//Leakcanary
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.0-beta-3'

implementation project(':imagepicker')
}

0 comments on commit 43b72d7

Please sign in to comment.