Android CameraUtil 快速集成實現系統相機拍照 End

   今天又要加打開相機拍照並且上傳圖片的功能。很多項目都會用到,所以一時興起,寫了個封裝類,希望在其他項目中,能夠快速引入相機拍照系統。

如何配置:

/*
* 1.首先在AndroidManifest中複製以下代碼,加入provider,避免在7.0以上的手機崩潰(因爲7.0修改了uri的權
* 限,不在直接提供外部調用)
*/
 <provider
     android:name="android.support.v4.content.FileProvider"
     android:authorities="com.hjl.artisan.fileProvider"
     android:exported="false"
     android:grantUriPermissions="true">
      <meta-data
             android:name="android.support.FILE_PROVIDER_PATHS"
             android:resource="@xml/file_paths" />
 </provider>

/*
*  新建文件res\xml\file_paths.xml,文件內容如下
*/
<paths>
    <!--path:需要臨時授權訪問的路徑(.代表所有路徑)-->
    <!--name:就是你給這個訪問路徑起個名字-->
    <external-path name="external-path" path="CameraPath" />
</paths>

如何使用:

//啓動相機
cameraUtil.gotoCaptureRaw(activity)

//相機回調
 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if(requestCode==CameraUtil.REQUEST_CODE_CAPTURE_RAW&&resultCode== Activity.RESULT_OK){
            CameraUtil.imageFile?.let {
                cameraUtil.compressImage(it,object:CameraUtil.CallBack{
                    override fun compressImageComplete(imgBitmap: Bitmap,file:File) {
                         //TODO
                    }
                })
            }
        }
    }

CameraUtil源碼:

package com.hjl.artisan.app

import android.Manifest
import android.app.Activity
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import android.support.v4.content.FileProvider
import android.util.Log
import android.widget.Toast
import com.wusy.wusylibrary.util.permissions.PermissionsManager
import com.wusy.wusylibrary.util.permissions.PermissionsResultAction
import java.io.*
import java.text.SimpleDateFormat
import java.util.*
import kotlin.concurrent.thread

class CameraUtil {

    val TAG: String = "CameraUtil"

    //拍照(返回原始圖)
    companion object {
        var imageFile: File? = null     //拍照後保存的照片
        var imgUri: Uri? = null         //拍照後保存的照片的uri
        val AUTHORITY = "com.hjl.artisan.fileProvider" //FileProvider的簽名(後面會介紹)
        val REQUEST_CODE_CAPTURE_RAW = 6 //startActivityForResult時的請求碼
    }

    /**
     * 打開系統相機
     */
    fun gotoCaptureRaw(activity: Activity) {
        imageFile = createImageFile()
        imageFile?.let {
            val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {  //如果是7.0以上,使用FileProvider,否則會報錯
                intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
                imgUri = FileProvider.getUriForFile(activity, AUTHORITY, it)
                intent.putExtra(MediaStore.EXTRA_OUTPUT, imgUri) //設置拍照後圖片保存的位置
            } else {
                intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(it)) //設置拍照後圖片保存的位置
            }
            intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()) //設置圖片保存的格式
            intent.resolveActivity(activity.packageManager)?.let {
                if (PermissionsManager.getInstance().hasPermission(activity, Manifest.permission.CAMERA)) {
                    activity.startActivityForResult(intent, REQUEST_CODE_CAPTURE_RAW) //調起系統相機
                } else {
                    Toast.makeText(activity, "打開相機失敗,需要獲取相機權限", Toast.LENGTH_SHORT).show()
                    PermissionsManager.getInstance().requestPermissionsIfNecessaryForResult(activity,
                        arrayOf(Manifest.permission.CAMERA), object : PermissionsResultAction() {
                            override fun onGranted() {
                                activity.startActivityForResult(intent, REQUEST_CODE_CAPTURE_RAW) //調起系統相機
                            }

                            override fun onDenied(permission: String) {

                            }
                        })
                }
            }
        }
    }

    //生成一個文件
    private fun createImageFile(isCrop: Boolean = false): File? {
        return try {
            var rootFile = File(Environment.getExternalStorageDirectory().toString() + File.separator + "CameraPath")
            if (!rootFile.exists())
                rootFile.mkdirs()
            val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
            val fileName = if (isCrop) "IMG_${timeStamp}_CROP.jpg" else "IMG_$timeStamp.jpg"
            File(rootFile.absolutePath + File.separator + fileName)
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }

    //壓縮圖片並顯示
    fun compressImage(file: File, listener: CallBack) {
        thread {
            var temp = System.currentTimeMillis()
            var bitmap = BitmapFactory.decodeFile(file.absolutePath)
            var compressBitmap = BitmapUtils.decodeBitmap(bitmap, 1080, 1080)
            Log.d("TAG", "原始圖片大小  ${bitmap.width} * ${bitmap.height}")
            Log.d("TAG", "壓縮後圖片大小  ${compressBitmap.width} * ${compressBitmap.height}")
            Log.d("TAG", "加載圖片耗時 ${System.currentTimeMillis() - temp}")
            listener.compressImageComplete(compressBitmap, file)
        }
    }

    open interface CallBack {
        fun compressImageComplete(imgBitmap: Bitmap, file: File)
    }

    /**
     * 壓縮圖片(質量壓縮)
     * 壓縮BitMap至指定大小以內,並且返回File
     * @param bitmap
     */
    fun compressImage(bitmap: Bitmap): File {
        var baos: ByteArrayOutputStream = ByteArrayOutputStream()
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);//質量壓縮方法,這裏100表示不壓縮,把壓縮後的數據存放到baos中
        var options = 100
        while (baos.toByteArray().size / 1024 > 500) {  //循環判斷如果壓縮後圖片是否大於500kb,大於繼續壓縮
            baos.reset()//重置baos即清空baos
            options -= 10//每次都減少10
            bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos)//這裏壓縮options%,把壓縮後的數據存放到baos中
            var length = baos.toByteArray().size
        }
        var format: SimpleDateFormat = SimpleDateFormat("yyyyMMddHHmmss")
        var date: Date = Date(System.currentTimeMillis())
        var filename = format.format(date)
        var file: File = File(Environment.getExternalStorageDirectory(), "$filename.png")
        try {
            var fos: FileOutputStream = FileOutputStream(file)
            try {
                fos.write(baos.toByteArray())
                fos.flush()
                fos.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        } catch (e: FileNotFoundException) {
            e.printStackTrace()
        }
//        recycleBitmap(bitmap)
        return file;
    }

    fun recycleBitmap(bm: Bitmap) {
        if (null != bm && !bm.isRecycled) {
            bm.recycle()
        }
    }
}

源碼:

wusyLibrary://wusylibrary/src/main/java/com/wusy/wusylibrary/util/CameraUtil .java
掃描文章末尾的二維碼,關注筆者的公衆號:飲水思源|wusy,回覆Android源碼獲取。感謝你的支持。

End

筆者的Github Blog,希望各位大大提意見,點個star,謝謝
傳送門:WusyBlog

求互粉互贊,互贊所有文章可以私聊我。哈哈,希望我們的原創文章能讓更多朋友看到,一起變強。

筆者新開通了微信公衆號——飲水思源|wusy 計劃持續運營,每日爲您分享Android乾貨、原創文章。微信掃描下方的二維碼關注我,開發學習路上不迷路。謝謝各位


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章