package com.zhaoyang.driver.base.local;
|
|
import android.Manifest
|
import android.annotation.SuppressLint
|
import android.annotation.TargetApi
|
import android.app.Activity
|
import android.app.Dialog
|
import android.content.ContentUris
|
import android.content.Context
|
import android.database.Cursor
|
import android.graphics.Bitmap
|
import android.graphics.BitmapFactory
|
import android.graphics.Matrix
|
import android.media.ExifInterface
|
import android.net.Uri
|
import android.os.Build
|
import android.os.Environment
|
import android.os.Handler
|
import android.provider.DocumentsContract
|
import android.provider.MediaStore
|
import android.util.Log
|
import android.widget.TextView
|
import androidx.loader.content.CursorLoader
|
import cn.sinata.xldutils.utils.sysErr
|
import com.example.emanagercar.ui.base.Local.BaseLoginActivity
|
import com.google.gson.Gson
|
import com.tbruyelle.rxpermissions2.RxPermissions
|
import com.ypx.imagepicker.ImagePicker
|
import com.ypx.imagepicker.bean.MimeType
|
import com.ypx.imagepicker.bean.SelectMode
|
import com.ypx.imagepicker.builder.MultiPickerBuilder
|
import com.zhaoyang.driver.R
|
import com.zhaoyang.driver.bean.StringBean
|
import com.zhaoyang.driver.netUtls.Api
|
import com.zhaoyang.driver.netUtls.callNet
|
import com.zhaoyang.driver.netUtls.getMapByAny
|
import com.zhaoyang.driver.ui.DialogUtil
|
import com.zhaoyang.driver.utils.BitmapUtil
|
import com.zhaoyang.driver.utils.OSSUtil
|
import kotlinx.android.synthetic.main.dialog_phone.view.*
|
import org.jetbrains.anko.toast
|
import java.io.*
|
import java.util.*
|
|
abstract class BasePhotoActivity : BaseLoginActivity() {
|
|
|
var phoneDialog: Dialog? = null
|
|
@SuppressLint("CheckResult")
|
fun showSelectPhone() {
|
showSelectPhone(1, false)
|
}
|
|
override fun tvInit(tv_code: TextView) {
|
}
|
|
override fun tvIniting(tv_code: TextView, time: String) {
|
|
}
|
|
|
|
var showNum = 0
|
|
/***
|
* 可选张数 selectNum
|
* isVideo 是否选择视频
|
*/
|
@SuppressLint("CheckResult")
|
fun showSelectPhone(selectNum: Int, isVideo: Boolean) {
|
showSelectPhone(selectNum, isVideo, "")
|
}
|
|
/***
|
* 可选张数 selectNum
|
* isVideo 是否选择视频
|
*/
|
@SuppressLint("CheckResult")
|
fun showSelectPhone(selectNum: Int, isVideo: Boolean, title: String) {
|
if (selectNum <= 0) {
|
return
|
}
|
val rxPermissions = RxPermissions(this)
|
rxPermissions.request(Manifest.permission.CAMERA)
|
.subscribe { aBoolean ->
|
if (aBoolean) {
|
phoneDialog = DialogUtil.getDialog(mContext, R.layout.dialog_phone)
|
phoneDialog?.let {
|
val view = DialogUtil.getView(phoneDialog!!)
|
if (!title.isEmpty()){
|
view.btn_title.text = title
|
}else{
|
view.btn_title.text = "选择照片"
|
}
|
view.button_cancel.setOnClickListener {
|
phoneDialog!!.dismiss()
|
}
|
view.btn_album.setOnClickListener {
|
openAlbum(selectNum, isVideo)
|
phoneDialog!!.dismiss()
|
}
|
|
view.btn_phone.setOnClickListener {
|
openCarmra()
|
phoneDialog!!.dismiss()
|
}
|
}
|
} else {
|
showToast("请在应用权限页面开启相机权限")
|
}
|
}
|
|
}
|
|
|
fun openAlbum(selectNum: Int, isVideo: Boolean) {
|
var build: MultiPickerBuilder = ImagePicker.withMulti(WeChatPresenter()) //指定presenter
|
//设置选择的最大数
|
if (!isVideo) {
|
build.filterMimeTypes(MimeType.GIF)
|
.filterMimeTypes(MimeType.AVI)
|
.filterMimeTypes(MimeType.MP4)
|
}
|
build.setMaxCount(selectNum)
|
//设置列数
|
.setColumnCount(4)
|
//设置要加载的文件类型,可指定单一类型
|
.mimeTypes(MimeType.ofAll())
|
//设置需要过滤掉加载的文件类型
|
.showCamera(false)//显示拍照
|
.setPreview(false)//开启预览
|
//大图预览时是否支持预览视频
|
.setPreviewVideo(false)
|
//设置视频单选
|
.setVideoSinglePick(false)
|
//设置图片和视频单一类型选择
|
.setSinglePickImageOrVideoType(false)
|
//当单选或者视频单选时,点击item直接回调,无需点击完成按钮
|
.setSinglePickWithAutoComplete(true)
|
//显示原图
|
.setOriginal(false)
|
//显示原图时默认原图选项开关
|
.setDefaultOriginal(false)
|
//设置单选模式,当maxCount==1时,可执行单选(下次选中会取消上一次选中)
|
.setSelectMode(SelectMode.MODE_SINGLE)
|
//设置视频可选取的最大时长,同时也是视频可录制的最大时长
|
.setMaxVideoDuration(30000L)
|
//设置视频可选取的最小时长
|
.setMinVideoDuration(100L)
|
.pick(this) { items ->
|
showNum = items.size
|
for (item in items) {
|
var pathItem = getRealPathFromUri(mContext, item.uri)
|
pathItem?.let {
|
savePhone(pathItem, 1, item.uri)
|
}
|
}
|
}
|
}
|
|
private fun openCarmra() {
|
var name = System.currentTimeMillis().toString();//可为null
|
var isCopyInDCIM = true;//copy一份保存到系统相册文件
|
ImagePicker.takePhoto(this, name, isCopyInDCIM) {
|
showNum = 1
|
var pathItem = getRealPathFromUri(mContext, it[0].uri)
|
var uri = it[0].uri
|
pathItem?.let {
|
savePhone(pathItem, 2, uri)
|
}
|
}
|
}
|
|
/***
|
* 上传oss
|
*/
|
open fun savePhone(filePath: String, type: Int, uri: Uri) {
|
showDialog()
|
var copyFile = ""
|
Thread(
|
Runnable
|
{
|
if (filePath.endsWith("png") || filePath.endsWith("jpg")) {
|
getCameraPhotoOrientation(filePath)
|
copyFile = compressImage(filePath)
|
// val bitmap = getBitmapFormUri(this,uri)
|
// val bit = rotateBitmap(bitmap, rotate)
|
// val b = saveBmpToPath(bit, filePath)
|
// if (!b) {
|
// Handler(mainLooper).post {
|
// toast("旋转图片错误")
|
// }
|
// }
|
}
|
val key = "zhanoyang/" + UUID.randomUUID().toString() + filePath.substring(filePath.lastIndexOf("."))
|
val map = getMapByAny()
|
map["key"] = key
|
callNet(false, Api.getQnyToken,map){
|
val fromJson = Gson().fromJson(it, StringBean::class.java)
|
val ossUtil = OSSUtil(this)
|
ossUtil.uploadSingle(copyFile,key,fromJson.data, object : OSSUtil.OSSUploadCallBack() {
|
override fun onFinish(url: String?) {
|
super.onFinish(url)
|
showNum--
|
Handler(mainLooper).post {
|
Log.d("showNum==", "showNum==========" + showNum.toString())
|
sysErr(url)
|
if (showNum <= 0)
|
dismissDialog()
|
getPhoneUrl(url!!, type, copyFile)
|
getPhoneUrl(url, type)
|
}
|
}
|
|
override fun onFial(message: String?) {
|
super.onFial(message)
|
showNum--
|
}
|
})
|
}
|
|
// ossUtil.uploadSingle(filePath, object : OSSUtil.OSSUploadCallBack() {
|
// override fun onFinish(url: String) {
|
// super.onFinish(url)
|
// dismissDialog()
|
// getPhoneUrl(url,type)
|
// }
|
//
|
// override fun onFial(message: String) {
|
// super.onFial(message)
|
// dismissDialog()
|
// toast("上传失败")
|
// }
|
// })
|
}).start()
|
}
|
|
// 1 相册 2 照片
|
open fun getPhoneUrl(url: String, type: Int) {
|
|
}
|
|
open fun getPhoneUrl(url: String, type: Int, path: String) {
|
|
}
|
|
|
//复杂版处理 (适配多种API)
|
open fun getRealPathFromUri(
|
context: Context,
|
uri: Uri
|
): String? {
|
val sdkVersion: Int = Build.VERSION.SDK_INT
|
if (sdkVersion < 11) return getRealPathFromUri_BelowApi11(context, uri)
|
return if (sdkVersion < 19) getRealPathFromUri_Api11To18(
|
context,
|
uri
|
) else getRealPathFromUri_AboveApi19(context, uri)
|
}
|
|
/**
|
* 适配api19以上,根据uri获取图片的绝对路径
|
*/
|
@TargetApi(Build.VERSION_CODES.KITKAT)
|
private fun getRealPathFromUri_AboveApi19(
|
context: Context,
|
uri: Uri
|
): String? {
|
if (DocumentsContract.isDocumentUri(context, uri)) {
|
if (isExternalStorageDocument(uri)) {
|
val docId: String = DocumentsContract.getDocumentId(uri)
|
val split = docId.split(":").toTypedArray()
|
val type = split[0]
|
if ("primary".equals(type, ignoreCase = true)) {
|
return Environment.getExternalStorageDirectory().toString() + "/" + split[1]
|
}
|
} else if (isDownloadsDocument(uri)) {
|
val id: String = DocumentsContract.getDocumentId(uri)
|
val contentUri: Uri = ContentUris.withAppendedId(
|
Uri.parse("content://downloads/public_downloads"),
|
java.lang.Long.valueOf(id)
|
)
|
return getDataColumn(context, contentUri, null, null)
|
} else if (isMediaDocument(uri)) {
|
val docId: String = DocumentsContract.getDocumentId(uri)
|
val split = docId.split(":").toTypedArray()
|
val type = split[0]
|
val contentUri: Uri
|
contentUri = if ("image" == type) {
|
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
|
} else if ("video" == type) {
|
MediaStore.Video.Media.EXTERNAL_CONTENT_URI
|
} else if ("audio" == type) {
|
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
|
} else {
|
MediaStore.Files.getContentUri("external")
|
}
|
val selection = "_id=?"
|
val selectionArgs =
|
arrayOf(split[1])
|
return getDataColumn(context, contentUri, selection, selectionArgs)
|
}
|
} else if ("content".equals(uri.scheme, ignoreCase = true)) {
|
return getDataColumn(context, uri, null, null)
|
} else if ("file".equals(uri.scheme, ignoreCase = true)) {
|
return uri.path
|
}
|
return null
|
}
|
|
|
|
/**
|
* 适配api11-api18,根据uri获取图片的绝对路径
|
*/
|
private fun getRealPathFromUri_Api11To18(
|
context: Context,
|
uri: Uri
|
): String? {
|
var filePath: String? = null
|
val projection =
|
arrayOf<String>(MediaStore.Images.Media.DATA)
|
//这个有两个包不知道是哪个。。。。不过这个复杂版一般用不到
|
val loader = CursorLoader(context, uri, projection, null, null, null)
|
val cursor: Cursor? = loader.loadInBackground()
|
if (cursor != null) {
|
cursor.moveToFirst()
|
filePath = cursor.getString(cursor.getColumnIndex(projection[0]))
|
cursor.close()
|
}
|
return filePath
|
}
|
|
@Throws(FileNotFoundException::class, IOException::class)
|
open fun getBitmapFormUri(
|
ac: Activity,
|
uri: Uri?
|
): Bitmap? {
|
var input = ac.contentResolver.openInputStream(uri!!)
|
val onlyBoundsOptions =
|
BitmapFactory.Options()
|
onlyBoundsOptions.inJustDecodeBounds = true
|
onlyBoundsOptions.inDither = true //optional
|
onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888 //optional
|
BitmapFactory.decodeStream(input, null, onlyBoundsOptions)
|
input!!.close()
|
val originalWidth = onlyBoundsOptions.outWidth
|
val originalHeight = onlyBoundsOptions.outHeight
|
if (originalWidth == -1 || originalHeight == -1) return null
|
//图片分辨率以480x800为标准
|
val hh = 800f //这里设置高度为800f
|
val ww = 480f //这里设置宽度为480f
|
//缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
|
var be = 1 //be=1表示不缩放
|
if (originalWidth > originalHeight && originalWidth > ww) { //如果宽度大的话根据宽度固定大小缩放
|
be = (originalWidth / ww).toInt()
|
} else if (originalWidth < originalHeight && originalHeight > hh) { //如果高度高的话根据宽度固定大小缩放
|
be = (originalHeight / hh).toInt()
|
}
|
if (be <= 0) be = 1
|
//比例压缩
|
val bitmapOptions =
|
BitmapFactory.Options()
|
bitmapOptions.inSampleSize = be //设置缩放比例
|
bitmapOptions.inDither = true //optional
|
bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888 //optional
|
input = ac.contentResolver.openInputStream(uri)
|
val bitmap =
|
BitmapFactory.decodeStream(input, null, bitmapOptions)
|
input!!.close()
|
return compressImage(bitmap!!) //再进行质量压缩
|
}
|
|
/**
|
* 适配api11以下(不包括api11),根据uri获取图片的绝对路径
|
*/
|
private fun getRealPathFromUri_BelowApi11(
|
context: Context,
|
uri: Uri
|
): String? {
|
var filePath: String? = null
|
val projection =
|
arrayOf<String>(MediaStore.Images.Media.DATA)
|
val cursor: Cursor? = context.contentResolver.query(uri, projection, null, null, null)
|
if (cursor != null && cursor.moveToFirst()) {
|
filePath = cursor.getString(cursor.getColumnIndex(projection[0]))
|
cursor.close()
|
}
|
return filePath
|
}
|
|
/**
|
* 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.
|
*/
|
open fun getDataColumn(
|
context: Context, uri: Uri?, selection: String?,
|
selectionArgs: Array<String>?
|
): String? {
|
var cursor: Cursor? = null
|
val column: String = MediaStore.MediaColumns.DATA
|
val projection = arrayOf(column)
|
try {
|
cursor = context.contentResolver.query(
|
uri!!, projection, selection, selectionArgs,
|
null
|
)
|
if (cursor != null && cursor.moveToFirst()) {
|
val column_index: Int = cursor.getColumnIndexOrThrow(column)
|
return cursor.getString(column_index)
|
}
|
} catch (e: Exception) {
|
e.printStackTrace()
|
} finally {
|
if (cursor != null) cursor.close()
|
}
|
return null
|
}
|
|
/**
|
* @param uri The Uri to check.
|
* @return Whether the Uri authority is ExternalStorageProvider.
|
*/
|
open fun isExternalStorageDocument(uri: Uri): Boolean {
|
return "com.android.externalstorage.documents" == uri.authority
|
}
|
|
/**
|
* @param uri The Uri to check.
|
* @return Whether the Uri authority is DownloadsProvider.
|
*/
|
open fun isDownloadsDocument(uri: Uri): Boolean {
|
return "com.android.providers.downloads.documents" == uri.authority
|
}
|
|
/**
|
* @param uri The Uri to check.
|
* @return Whether the Uri authority is MediaProvider.
|
*/
|
open fun isMediaDocument(uri: Uri): Boolean {
|
return "com.android.providers.media.documents" == uri.authority
|
}
|
|
open fun getCompressBm(filePath: String?): Bitmap? {
|
var bm: Bitmap? = null
|
val options = BitmapFactory.Options()
|
options.inJustDecodeBounds = true
|
BitmapFactory.decodeFile(filePath, options)
|
// Calculate inSampleSize
|
// options.inSampleSize = calculateInSampleSize(options, 500, 500)
|
// Decode bitmap with inSampleSize set
|
options.inJustDecodeBounds = false
|
bm = BitmapFactory.decodeFile(filePath, options)
|
return bm
|
}
|
|
|
open fun getCameraPhotoOrientation(imagePath: String?): Int {
|
var rotate = 0
|
try {
|
val imageFile = File(imagePath)
|
val exif = ExifInterface(imageFile.absolutePath)
|
val orientation: Int = exif.getAttributeInt(
|
ExifInterface.TAG_ORIENTATION,
|
ExifInterface.ORIENTATION_NORMAL
|
)
|
when (orientation) {
|
ExifInterface.ORIENTATION_ROTATE_270 -> rotate = 270
|
ExifInterface.ORIENTATION_ROTATE_180 -> rotate = 180
|
ExifInterface.ORIENTATION_ROTATE_90 -> rotate = 90
|
}
|
// Log.v(TAG, "Exif orientation: " + orientation);
|
} catch (e: java.lang.Exception) {
|
e.printStackTrace()
|
}
|
return rotate
|
}
|
|
open fun rotateBitmap(bitmap: Bitmap?, rotate: Int): Bitmap? {
|
if (bitmap == null) return null
|
val w = bitmap.width
|
val h = bitmap.height
|
// Setting post rotate to 90
|
val mtx = Matrix()
|
mtx.postRotate(rotate.toFloat())
|
return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true)
|
}
|
|
open fun saveBmpToPath(bitmap: Bitmap?, filePath: String?): Boolean {
|
if (bitmap == null || filePath == null) {
|
return false
|
}
|
var result = false // 默认结果【n
|
val file = File(filePath)
|
var outputStream: OutputStream? = null // 文件输出流
|
try {
|
var num = 100
|
outputStream = FileOutputStream(file)
|
result = bitmap.compress(
|
Bitmap.CompressFormat.JPEG, num,
|
outputStream
|
) // 将图片压缩为JPEG格式写到文件输出流,100是最大的质量程度
|
} catch (e: java.lang.Exception) {
|
e.printStackTrace()
|
} finally {
|
if (outputStream != null) {
|
try {
|
outputStream.close() // 关闭输出流
|
} catch (e: IOException) {
|
e.printStackTrace()
|
}
|
}
|
return result
|
}
|
}
|
open fun compressImage(image: Bitmap): Bitmap? {
|
val baos = ByteArrayOutputStream()
|
image.compress(
|
Bitmap.CompressFormat.JPEG,
|
100,
|
baos
|
) // 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
|
var options = 90
|
while (baos.toByteArray().size / 1024 > 3000) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
|
baos.reset() // 重置baos即清空baos
|
image.compress(
|
Bitmap.CompressFormat.JPEG,
|
options,
|
baos
|
) // 这里压缩options%,把压缩后的数据存放到baos中
|
options -= 10 // 每次都减少10
|
}
|
val isBm =
|
ByteArrayInputStream(baos.toByteArray()) // 把压缩后的数据baos存放到ByteArrayInputStream中
|
return BitmapFactory.decodeStream(
|
isBm,
|
null,
|
null
|
)
|
}
|
|
|
open fun compressImage(filePath: String?): String {
|
if (filePath == null) {
|
return ""
|
}
|
var copyPath = ""
|
if (filePath.endsWith("png")) {
|
copyPath =
|
getExternalFilesDir(Environment.DIRECTORY_PICTURES)!!.absolutePath + "/" + System.currentTimeMillis() + ".png"
|
} else if (filePath.endsWith("jpg")) {
|
copyPath =
|
getExternalFilesDir(Environment.DIRECTORY_PICTURES)!!.absolutePath + "/" + System.currentTimeMillis() + ".jpg"
|
} else {
|
toast("不支持的文件类型")
|
}
|
copyFile(filePath, copyPath)
|
var file = File(copyPath)
|
var bitmap = BitmapFactory.decodeFile(copyPath)
|
var num = 100
|
var baos = ByteArrayOutputStream()
|
bitmap.compress(Bitmap.CompressFormat.JPEG, num, baos)
|
while (baos.toByteArray().size.toFloat() / 1024f / 1024f > 1f) {
|
baos.reset()
|
bitmap.compress(Bitmap.CompressFormat.JPEG, num, baos);
|
num -= 10
|
if (num <= 0) {
|
break
|
}
|
}
|
var isBm = ByteArrayInputStream(baos.toByteArray())
|
var bitmapby = BitmapFactory.decodeStream(isBm, null, null)
|
copyPath = BitmapUtil.bitmap2File(this, bitmapby, System.currentTimeMillis().toString())
|
return copyPath
|
}
|
|
|
open fun copyFile(oldPath: String?, newPath: String?) {
|
try {
|
var bytesum = 0
|
var byteread = 0
|
val oldfile = File(oldPath)
|
if (oldfile.exists()) { //文件存在时
|
val inStream: InputStream = FileInputStream(oldPath) //读入原文件
|
val fs = FileOutputStream(newPath)
|
val buffer = ByteArray(1444)
|
while (inStream.read(buffer).also { byteread = it } != -1) {
|
bytesum += byteread //字节数 文件大小
|
println(bytesum)
|
fs.write(buffer, 0, byteread)
|
}
|
inStream.close()
|
}
|
} catch (e: java.lang.Exception) {
|
println("复制单个文件操作出错")
|
e.printStackTrace()
|
}
|
}
|
|
}
|