今天又要加打開相機拍照並且上傳圖片的功能。很多項目都會用到,所以一時興起,寫了個封裝類,希望在其他項目中,能夠快速引入相機拍照系統。
如何配置:
/*
* 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乾貨、原創文章。微信掃描下方的二維碼關注我,開發學習路上不迷路。謝謝各位