Android辅助H5做一个Web版的相册功能
Posted 汤米粥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android辅助H5做一个Web版的相册功能相关的知识,希望对你有一定的参考价值。
主要是两个功能,返回相册列表给H5,和选中图片。
1.获取相册列表用伪造的图片http url,让H5容器先拿到列表,然后在img请求具体图片的时候使用shouldInterceptRequest拦截,再返回压缩的图片流。因为在获取列表的时候如果就都要返回图片的实体base64会很慢。 2.在选中某一个图片时返回真实未压缩的图片的base64
class TestActivity : AppCompatActivity()
var mUploadCallbackAboveL: ValueCallback<Array<Uri?>?>? = null
var mUploadMessage: ValueCallback<Uri?>? = null
private val REQUEST_LIST_CODE = 999
private val REQUEST_BUY_VIP = 100 //去到会员页的requestCode都是100
private var mProjectModel: MyProjectModel = MyProjectModel()
private var mFrom = ""
private var mWorkId = ""
private var mTemplateId = ""
private var mType = ""
private var mUrl = ""
private var title = ""
private var showToolbar = false
private var albumnList: LinkedHashMap<String, AlbumBean> = linkedMapOf() //相册列表+每个相册里的照片列表
private var onlyAblumnList: ArrayList<OnlyAlbumBean> = arrayListOf()
private var allPicList: ArrayList<ImageBean>? = arrayListOf() //全部照片列表
private var firstPagePictures: ArrayList<ImageBean>? = null //第一页预加载
val mGson = Gson()
var isLoadComplete = false
companion object
private var mClickTime: Long = 0
@JvmStatic
fun open(context: Context, url: String, title: String, showToolbar: Boolean)
if (System.currentTimeMillis() - mClickTime > 500)
mClickTime = System.currentTimeMillis()
val intent = Intent(context, NetEditorActivity::class.java)
intent.putExtra("url", url)
intent.putExtra("from", "template")
intent.putExtra("showToolbar", showToolbar)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
@JvmStatic
fun open(context: Context, workId: String, type: String)
if (System.currentTimeMillis() - mClickTime > 500)
mClickTime = System.currentTimeMillis()
val intent = Intent(context, NetEditorActivity::class.java)
intent.putExtra("work_id", workId)
intent.putExtra("type", type)
intent.putExtra("from", "project")
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
private var enterTime: Long = 0
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
StatusBarUtil.setColor(this, Color.parseColor("#141414"))
StatusBarUtil.setLightMode(this)
ISNav.getInstance().init context, path, imageView -> Glide.with(context!!).load(path).into(imageView)
setContentView(R.layout.activity_net_editor)
enterTime = System.currentTimeMillis()
initProject()
val settings = wv_editor.settings
settings.javascriptEnabled = true
settings.allowFileAccess = true
settings.allowContentAccess = true
settings.domStorageEnabled = true
settings.databaseEnabled = true
wv_editor.setBackgroundColor(0)
wv_editor.background.alpha = 0
settings.setGeolocationEnabled(true)
settings.setAppCacheEnabled(true)
//允许webview对文件的操作
settings.setAllowUniversalAccessFromFileURLs(true);
settings.setAllowFileAccess(true);
settings.setAllowFileAccessFromFileURLs(true);
settings.userAgentString = settings.userAgentString + " HELLO_android/" + SystemUtil.getVersionCode(HelloApplicationLike.getContext())
// wv_editor.loadUrl(
// "$url/?page_id=$mWorkId&uid=$userManager.userId&works_type=$mType&env=$env&runtime=Android"
// )
// !!!! TO DO加一个参数,后面要删掉********************//
Log.d("hello", "url:$mUrl")
// mUrl = "http://192.168.70.220:7788/?token=24e5fad7114d4d8380e6d175c6ca04d1&page_id=QL21RX0HW602040976&uid=602040976&works_type=poster&env=staging&dev_dll=http://192.168.70.220:22111&debug_photo=true"
wv_editor.loadUrl(mUrl + "&debug_photo=true")
val api2 = JsCallback()
wv_editor.addJavascriptInterface(
api2,
"nativeApi"
)
wv_editor.webViewClient = object : WebViewClient()
override fun onPageFinished(view: WebView, url: String?)
tv_common_title.postDelayed(Runnable tv_common_title.text = view.title , 1000)
override fun shouldInterceptRequest(webview: WebView?, webResourceRequest: WebResourceRequest): WebResourceResponse?
var input: FileInputStream
var url = webResourceRequest.getUrl().toString();
var key = "storage/emulated";
var host = MkHost.getInstance().getCommonWapHost()
host = host.substring(0, host.length - 1)
Log.e("xxx-host", host)
/*如果请求包含约定的字段 说明是要拿本地的图片*/
if (url.contains(key))
Log.e("xxx", "请求图片" + url + ":" + System.currentTimeMillis())
var imgPath = url.replace(host, "");
try
/*重新构造WebResourceResponse 将数据已流的方式传入*/
var response: WebResourceResponse? = null
Log.e("xxx", "开始压缩图片" + url + ":" + System.currentTimeMillis())
//压缩图片
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeFile(imgPath, options)
val inSampleSize = BitmapUtils.calculateInsampleSize(options, 200, 400)
options.inSampleSize = inSampleSize
options.inJustDecodeBounds = false
var bitmap = BitmapFactory.decodeFile(imgPath, options)
// Log.e("xxx", "开始压缩图片1" + url + ":" + System.currentTimeMillis())
val stream = ByteArrayOutputStream()
bitmap!!.compress(Bitmap.CompressFormat.JPEG, 100, stream)
var bis = ByteArrayInputStream(stream.toByteArray())
response = WebResourceResponse("image/jpg", "UTF-8", bis);
// Log.e("xxx", "开始压缩图片2" + url + ":" + System.currentTimeMillis())
// Log.e("xxx", "返回图片" + url + ":" + System.currentTimeMillis())
return response;
catch (e: Exception)
e.printStackTrace();
return null
// 自定义图片加载器
ISNav.getInstance().init(ImageLoader context: Context?, path: String?, imageView: ImageView? -> Glide.with(context!!).load(path).into(imageView!!) )
wv_editor.webChromeClient = object : WebChromeClient()
override fun onConsoleMessage(consoleMessage: com.tencent.smtt.export.external.interfaces.ConsoleMessage?): Boolean
//获取log的级别
when (consoleMessage?.messageLevel())
//将error信息上报到服务端
com.tencent.smtt.export.external.interfaces.ConsoleMessage.MessageLevel.ERROR ->
Log.e("editor_error", consoleMessage.message() + " at " + consoleMessage.sourceId() + ":" + consoleMessage.lineNumber())
val errorMsg = consoleMessage.message() + " at " + consoleMessage.sourceId() + ":" + consoleMessage.lineNumber()
Log.e("editor_error", DefaultUserRepo.getInstance().getLoginUid() ?: "")
Log.e("editor_error", mProjectModel.workId)
Log.e("editor_error", ((System.currentTimeMillis() - enterTime) / 1000).toString())
var params: HashMap<String, String?> = HashMap()
params.put("uid", DefaultUserRepo.getInstance().getLoginUid())
params.put("id", mProjectModel?.workId)
params.put("time", ((System.currentTimeMillis() - enterTime) / 1000).toString())
var helloLog: HelloLogErrorBean = HelloLogErrorBean("error", "wap editor", "", GsonUtils.toJson(params), errorMsg)
HelloLogManager.errorLog(helloLog)
return super.onConsoleMessage(consoleMessage);
// Android > 5.0 调用这个方法
override fun onShowFileChooser(
webView: WebView?,
valueCallback: ValueCallback<Array<Uri?>?>?,
fileChooserParams: FileChooserParams?
): Boolean
mUploadCallbackAboveL = valueCallback
choosePicture()
return true
// Android > 4.1.1 调用这个方法
override fun openFileChooser(
uploadMsg: ValueCallback<Uri?>?,
acceptType: String?, capture: String?
)
mUploadMessage = uploadMsg
choosePicture()
// 3.0 + 调用这个方法
fun openFileChooser(
uploadMsg: ValueCallback<Uri?>?,
acceptType: String?
)
mUploadMessage = uploadMsg
choosePicture()
// Android < 3.0 调用这个方法
fun openFileChooser(uploadMsg: ValueCallback<Uri?>?)
mUploadMessage = uploadMsg
choosePicture()
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?)
super.onActivityResult(requestCode, resultCode, data)
// 图片选择结果回调
if (requestCode == REQUEST_LIST_CODE && resultCode == RESULT_OK && data != null)
val pathList: ArrayList<String>? = data.getStringArrayListExtra("result")
if (pathList != null && pathList.size > 0)
val result = Uri.parse("file://" + pathList[0])
if (mUploadMessage != null)
mUploadMessage!!.onReceiveValue(result)
mUploadMessage = null
val results = arrayOf(result)
if (mUploadCallbackAboveL != null)
mUploadCallbackAboveL!!.onReceiveValue(results)
mUploadCallbackAboveL = null
//会员页购买成功,刷新编辑器
if (requestCode == REQUEST_BUY_VIP && resultCode == RESULT_OK)
Log.e("xxx", "刷新")
wv_editor.reload()
if (resultCode == RESULT_CANCELED || data == null)
if (mUploadMessage != null)
mUploadMessage!!.onReceiveValue(null)
mUploadMessage = null
if (mUploadCallbackAboveL != null)
mUploadCallbackAboveL!!.onReceiveValue(null)
mUploadCallbackAboveL = null
//从结算列表页面过来
if (requestCode == RequestCodes.EDITOR_BUY_MATERIALS && resultCode == RESULT_OK)
Log.e("xxx", "去到分享")
wv_editor.reload() //刷新编辑器
routeToSharePoster(mWorkId)
private fun initProject()
mFrom = intent.extras?.getString("from") ?: ""
mTemplateId = intent.extras?.getString("template_id") ?: ""
mWorkId = intent.extras?.getString("work_id") ?: ""
mType = intent.extras?.getString("type") ?: ""
mUrl = intent.extras?.getString("url") ?: ""
showToolbar = intent.extras?.getBoolean("showToolbar", false) ?: false
Log.d("hellolog", "mUrl:$mUrl")
// mUrl = "https://hellopicture.oss-cn-beijing.aliyuncs.com/app_common/android_ab/js_demo.html" //测试网页
if (showToolbar)
layout_common_title.visibility = View.VISIBLE
fl_common_back.setOnClickListener
finish()
else
layout_common_title.visibility = View.GONE
mProjectModel.workId = mWorkId
mProjectModel.type = mType
val userManager = UserManager.getInstance()
mProjectModel.uid = userManager.userId
private var mHandler: Handler? = Handler()
private fun choosePicture()
val config = ISListConfig.Builder()
.multiSelect(false)
.rememberSelected(false)
.statusBarColor(Color.parseColor("#141414"))
.backResId(R.mipmap.icon_new_back)
.title("选择图片")
.titleColor(Color.WHITE)
.titleBgColor(Color.parseColor("#141414"))
.needCrop(false)
.needCamera(true)
.maxNum(1)
.build()
ISNav.getInstance().toListActivity(this, config, REQUEST_LIST_CODE)
// Log.e("xxx-", "查看相册")
// PermissionsManager.getInstance().requestPermissionsIfNecessaryForResult(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
// object : PermissionsResultAction()
// override fun onGranted()
mUploadCallbackAboveL!!.onReceiveValue(getSystemPhotoList(this@NetEditorActivity))
// ToastUtil.showSuccess("获取相册成功")
//
//
// override fun onDenied(permission: String)
// ToastUtil.showFailMessage("请在系统权限设置中找到HELLO开启存储权限")
// mUploadCallbackAboveL!!.onReceiveValue(arrayOf())
//
// )
class ImageBean(var image: String?, var assetId: String?)
/**
* start 开始位置
* limit 一页数量
* albumn 相册目录
*/
fun getPhotoList(context: Context, start: Int, limit: Int, albumn: String): ArrayList<ImageBean>?
val result: ArrayList<ImageBean> = arrayListOf()
val uri: Uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val contentResolver: ContentResolver = context.contentResolver
val cursor: Cursor = contentResolver.query(uri, null, null, null, MediaStore.Images.ImageColumns.DATE_ADDED + " DESC")!!
// val uri: Uri = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI
//
// val projection = arrayOf<String>(MediaStore.Images.Thumbnails._ID, MediaStore.Images.Thumbnails.IMAGE_ID, MediaStore.Images.Thumbnails.DATA)
//
//
// val contentResolver: ContentResolver = context.contentResolver
// val cursor: Cursor = contentResolver.query(uri, projection, null, null,null)!!
if (cursor == null || cursor.getCount() <= 0) return null // 没有图片
var position = 0
cursor.moveToPosition(start)
var host = MkHost.getInstance().getCommonWapHost()
host = host.substring(0, host.length - 1)
while (cursor.moveToNext() && position < limit)
val index: Int = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
val path: String = cursor.getString(index) // 文件地址
//压缩图片
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeFile(path, options)
val inSampleSize = BitmapUtils.calculateInsampleSize(options, 240, 480)
options.inSampleSize = inSampleSize
options.inJustDecodeBounds = false
var bitmap = BitmapFactory.decodeFile(path, options)
//将Bitmap换成流传给H5
val stream = ByteArrayOutputStream()
bitmap!!.compress(Bitmap.CompressFormat.JPEG, 100, stream)
result.add(ImageBean("data:image/jpeg;base64," + Base64.encodeToString(stream.toByteArray(), Base64.DEFAULT).replace("\\n", ""), path))
Log.e("xxx-$position", path)
position++
cursor.close()
// else
// var list = File(albumn).listFiles() // list null 不允许这样遍历,拿不到子目录内容
// list?.forEach
// result.add(ImageBean("http://192.168.70.220:7788" + it, ""))
//
//
return result
private fun getPhotoListNew(start: Int, limit: Int, albumn: String): ArrayList<ImageBean>?
var picList: ArrayList<ImageBean> = arrayListOf()
var position = 0
var inputStream: InputStream? = null
if (albumn.isNullOrEmpty())
var image: ImageBean? = null
while (position < limit)
if (allPicList == null || start + position >= allPicList?.size!!)
break
image = allPicList?.get(start + position)
// val base64Str = getSmallImageAndBase64(image?.assetId!!)
// image?.image = base64Str
picList?.add(image!!)
position++
else
//选中的相册
var list = albumnList[albumn]
var image: ImageBean? = null
while (position < limit)
if ((start + position) < 0 || start + position >= list!!.images!!.size) break
image = list!!.images?.get(start + position)!!
picList?.add(image)
position++
return picList
private fun getSmallImageAndBase64(imagePath: String?): String
Log.e("xxx-", "开始压缩图片:" + imagePath)
var base64ImageStr: String? = null
//压缩图片
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeFile(imagePath, options)
val inSampleSize = BitmapUtils.calculateInsampleSize(options, 240, 480)
options.inSampleSize = inSampleSize
options.inJustDecodeBounds = false
var bitmap = BitmapFactory.decodeFile(imagePath, options)
//将Bitmap换成流传给H5
val stream = ByteArrayOutputStream()
bitmap!!.compress(Bitmap.CompressFormat.JPEG, 50, stream)
Log.e("xxx-", "结束压缩图片:" + imagePath)
Log.e("xxx-", "开始base64图片:" + imagePath)
base64ImageStr = "data:image/jpeg;base64," + Base64.encodeToString(stream.toByteArray(), Base64.DEFAULT).replace("\\n", "")
//把缩略图存起来?
Log.e("xxx-", "结束base64图片:" + imagePath)
return base64ImageStr
private fun fileBase64String(path: String): String?
return try
val fis = FileInputStream(path) //转换成输入流
val baos = ByteArrayOutputStream()
val buffer = ByteArray(1024)
var count = 0
while (fis.read(buffer).also count = it >= 0)
baos.write(buffer, 0, count) //读取输入流并写入输出字节流中
fis.close() //关闭文件输入流
return Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT).replace("\\n", "")
catch (e: java.lang.Exception)
null
override fun onBackPressed()
// val jsonObject = JSONObject()
// val userInfo = UserInfo()
// userInfo.token = UserManager.getInstance().token
// userInfo.uid = UserManager.getInstance().userId
// jsonObject.put("type", "NATIVE")
// jsonObject.put("userInfo", userInfo)
// val shareStr = "'type': 'HORouter', 'data':'url': 'vip' "
// JS_MESSAGE_MODEL(shareStr)
// bridgeBack()
// val shareStr = "'type': 'HORouter', 'params':'url': 'hello://home/vip/vipActivity' "
// val shareStr = "'type': 'HORouter', 'params':'url': 'hello://posterShare?width=720&height=1280&previewUrl=www.baidu.com' "
// APP_INVOKE(shareStr)
if (isLoadComplete)
bridgeBack()
else
// finish()
private fun bridgeBack()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
wv_editor.evaluateJavascript("window.onJsBridgeBack()")
if (it != "false")
finish()
private fun routeToSharePosterWatermark(workId: String = "")
mWorkId = workId
val api = NetworkProvider.getInstance().provide(HttpApi::class.java)
api.getWorkDetail2(UserManager.getInstance().userId, mWorkId)
.compose(RxUtils.ioMain())
.subscribe(object : DefaultObserver<MyProjectModel?>()
override fun onFailure(throwable: Throwable)
override fun onSubscribe(d: Disposable)
override fun onNext(myProjectModel: MyProjectModel)
mProjectModel = myProjectModel
PosterImagePreviewSavedActivity.open(
this@NetEditorActivity,
false,
mProjectModel.templateId,
mProjectModel.title,
mProjectModel.categoryId,
mProjectModel.secondaryCategoryId,
mProjectModel.spec,
mProjectModel,
)
)
private fun routeToSharePoster(workId: String = "")
mWorkId = workId
val api = NetworkProvider.getInstance().provide(HttpApi::class.java)
api.getWorkDetail2(UserManager.getInstance().userId, mWorkId)
.compose(RxUtils.ioMain())
.subscribe(object : DefaultObserver<MyProjectModel?>()
override fun onFailure(throwable: Throwable)
override fun onSubscribe(d: Disposable)
override fun onNext(myProjectModel: MyProjectModel)
mProjectModel = myProjectModel
Router.getInstance()
.build(RouterConstants.PROJECT_POSTER_SETTING_ACTIVITY)
.with(Bundle().apply
putParcelable(EXTRA_DATA, mProjectModel)
putBoolean(EXTRA_IS_FROM_SETTING, true)
)
.navigation()
)
private fun routeToShareH5(workId: String = "")
mWorkId = workId
val api = NetworkProvider.getInstance().provide(HttpApi::class.java)
api.getWorkDetail2(UserManager.getInstance().userId, mWorkId)
.compose(RxUtils.ioMain())
.subscribe(object : DefaultObserver<MyProjectModel?>()
override fun onFailure(throwable: Throwable)
override fun onSubscribe(d: Disposable)
override fun onNext(myProjectModel: MyProjectModel)
mProjectModel = myProjectModel
Router.getInstance()
.build(RouterConstants.PROJECT_SETTING_ACTIVITY)
.with(Bundle().apply
putParcelable(EXTRA_DATA, mProjectModel)
putBoolean(EXTRA_IS_FROM_SETTING, true)
putString("title", "分享作品")
)
.withString("from", "")
.navigation()
)
private fun routeToShareH5Clear(workId: String = "")
mWorkId = workId
val api = NetworkProvider.getInstance().provide(HttpApi::class.java)
api.getWorkDetail2(UserManager.getInstance().userId, mWorkId)
.compose(RxUtils.ioMain())
.subscribe(object : DefaultObserver<MyProjectModel?>()
override fun onFailure(throwable: Throwable)
override fun onSubscribe(d: Disposable)
override fun onNext(myProjectModel: MyProjectModel)
mProjectModel = myProjectModel
Router.getInstance()
.build(RouterConstants.PROJECT_SETTING_ACTIVITY)
.with(Bundle().apply
putParcelable(EXTRA_DATA, mProjectModel)
putBoolean(EXTRA_IS_FROM_SETTING, true)
putString("title", "分享作品")
)
.withString("from", "")
.navigation()
)
fun testShare(para: String)
val jsonType = object : TypeToken<ShareInfo>() .type
val shareInfo = mGson.fromJson<ShareInfo>(para, jsonType)
if (shareInfo.type == "wechat")
ShareUtil.shareUrlToWxNoImage(this@NetEditorActivity, shareInfo.url, shareInfo.title, shareInfo.content, shareInfo.isCircle
?: false)
fun saveBase64Image(base64: String?)
val camara = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
// 首先保存图片
// 首先保存图片
var appDir = File(camara, "HELLO")
if (!appDir.exists())
val success = appDir.mkdirs()
if (!success)
appDir = camara
if (!appDir.exists())
throw RuntimeException(getString(R.string.msg_error_save_to_gallery))
PermissionsManager.getInstance().requestPermissionsIfNecessaryForResult(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
object : PermissionsResultAction()
override fun onGranted()
BitmapUtils.saveBase64ToFile(this@NetEditorActivity, base64, appDir.absolutePath)
override fun onDenied(permission: String)
ToastUtil.showFailMessage("保存失败!因为没有读写SD卡权限\\n请在系统权限设置中找到HELLO开启存储权限")
)
inner class JsCallback()
@JavascriptInterface
fun APP_INVOKE(para: String)
try
Log.d("hellolog", "para:$para")
val type1 = object : TypeToken<JsPara>() .type
val object1 = mGson.fromJson<JsPara>(para, type1)
when (object1.type)
"HORouter" ->
val type2 = object : TypeToken<RoutePara>() .type
val object2 = mGson.fromJson<RoutePara>(object1.params, type2)
object2.url?.let
val tempUri = it.toUri()
when (tempUri.host + tempUri.path)
"home/vip/vipActivity" ->
var senior = tempUri.getQueryParameter("is_senior")
var forward_page_name = tempUri.getQueryParameter("forward_page_name");
var forward_module = tempUri.getQueryParameter("forward_module")
VipTrackParam.forward_module = forward_module ?: ""
VipTrackParam.forward_page_name = forward_page_name ?: ""
VipTrackParam.vip_page_type = senior ?: "true"
JumpUtil().openVipPageForResult(this@NetEditorActivity, true, "", false, null, REQUEST_BUY_VIP)
"posterShare" ->
routeToSharePoster(
tempUri.getQueryParameter("workId") ?: mWorkId,
)
"posterShareWatermark" ->
routeToSharePosterWatermark(
tempUri.getQueryParameter("workId") ?: mWorkId,
)
"h5Share" ->
routeToShareH5(tempUri.getQueryParameter("workId") ?: mWorkId)
"h5Clear" ->
routeToShareH5Clear(tempUri.getQueryParameter("workId")
?: mWorkId)
"support.qq.com/products/162011/" ->
CommonWebViewActivity.openPost(this@NetEditorActivity, "https://support.qq.com/products/162011/", "意见反馈")
"materialShoppingList" ->
val workId = tempUri.getQueryParameter("workId") ?: mWorkId
if (!workId.isNullOrEmpty())
mWorkId = workId
val templateType = tempUri.getQueryParameter("templateType")
val forward_page_name = tempUri.getQueryParameter("editor")
var previewUrl: String? = ""
mType = templateType ?: ""
if ("poster".equals(templateType))
else
previewUrl = tempUri.getQueryParameter("previewUrl")
val repository = MaterialsPurchaseRepository.newInstance()
var observable: Observable<List<MaterialPurchase>> = repository.getAllNeedPurchaseMaterialsNewEditor(workId)
observable.compose(RxUtils.ioMain())
.doOnSubscribe disposable: Disposable? ->
.subscribe(object : DefaultObserver<List<MaterialPurchase?>?>()
override fun onFailure(throwable: Throwable)
override fun onSubscribe(d: Disposable)
override fun onNext(materialPurchases: List<MaterialPurchase?>)
if (materialPurchases.isNotEmpty())
MaterialsPurchaseActivity.Companion.openForResult(
"new_editor",
this@NetEditorActivity,
workId,
mType,
materialPurchases!! as List<MaterialPurchase>,
RequestCodes.EDITOR_BUY_MATERIALS,
EditorTrackUtil.getCommonParamsJsonFromEditorModel(mProjectModel),
previewUrl ?: ""
)
else
routeToShareH5(tempUri.getQueryParameter("workId")
?: mWorkId)
)
else ->
if (it.contains("https"))
var url = URLDecoder.decode(it)
NetEditorActivity.open(this@NetEditorActivity, url, "", true)
"HOLifecycle" ->
"HOShare" ->
val type2 = object : TypeToken<ShareInfo>() .type
val object2 = mGson.fromJson<ShareInfo>(object1.params, type2)
if (object2.type == "wechat")
ShareUtil.shareUrlToWxNoImage(
this@NetEditorActivity,
object2.url,
object2.title,
object2.content,
object2.isCircle ?: false
)
"HOToast" ->
val type2 = object : TypeToken<ToastPara>() .type
val object2 = mGson.fromJson<ToastPara>(object1.params, type2)
ToastUtil.showNormalMessage(object2.message ?: "")
"HOBack" ->
finish()
"HOUserInfo" ->
var userInfo: UserInfo? = null
if (DefaultUserRepo.getInstance().getUserVips().isEmpty())
userInfo = UserInfo(
token = UserManager.getInstance().token,
uid = UserManager.getInstance().userId
).copy()
else
userInfo = UserInfo(
token = UserManager.getInstance().token,
uid = UserManager.getInstance().userId,
vipInfo = DefaultUserRepo.getInstance().getVipEntrance(
HelloConfigUtils.isInABGroup(HelloConfigUtils.VIP_POSITION), HelloConfigUtils.isInABGroup(
HelloConfigUtils.VIP_STRENGTHEN_MONTHLY_PRICE
)
).copy()
)
val callbackStr = object1.jsCbFnName ?: ""
val js = "window.$callbackStr($mGson.toJson(userInfo))"
Log.e("xxx-", js)
runOnUiThread
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
wv_editor.evaluateJavascript(js, null)
"HOAppVersion" ->
val callbackStr = object1.jsCbFnName ?: ""
val js = "window.$callbackStr(\\"version\\":\\"$SystemUtil.getVersionName(this@NetEditorActivity)\\")"
Log.e("xxx-", js)
runOnUiThread
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
wv_editor.evaluateJavascript(js, null)
"HOVibrate" ->
val type2 = object : TypeToken<VibratePara>() .type
val object2 = mGson.fromJson<VibratePara>(object1.params, type2)
VibrateUtil.vibrate(this@NetEditorActivity, object2.time ?: 50L)
"HOSaveImage" ->
val type2 = object : TypeToken<SaveImage>() .type
val object2 = mGson.fromJson<SaveImage>(object1.params, type2)
if (object2?.url != null)
var str = object2.url!!.split(",")
saveBase64Image(str[1])
"HOAlbumList" ->
Log.e("xxx", "HOAlbumList")
val callbackStr = object1.jsCbFnName ?: ""
/**
*
* Android装载器Loader是从Android 3 引入的 ,使用相关API 可以从数据库,网络,内容管理者等数据源中加载数据,然后显示在 Fragment 或 Activity上
*
* Loader在单独的线程上运行,以防止 UI 出现卡顿或无响应。
*
* Loader通过在事件发生时提供回调方法来简化线程管理。
*
* Loader在配置更改中持久保存和缓存结果,以防止重复查询。
*
* Loader可以实现一个观察者来监控底层数据源的变化。例如,CursorLoader自动注册一个ContentObserver以在数据更改时触发重新加载。
*
*/
val mLoaderCallback: LoaderManager.LoaderCallbacks<Cursor?> = object : LoaderManager.LoaderCallbacks<Cursor?>
private val IMAGE_PROJECTION = arrayOf(
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media._ID)
override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor?>
if (id == 0)
return CursorLoader(this@NetEditorActivity,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION,
null, null, MediaStore.Images.Media.DATE_ADDED + " DESC")
else
return CursorLoader(this@NetEditorActivity,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION, IMAGE_PROJECTION[0] + " not like '%.gif%'", null, MediaStore.Images.Media.DATE_ADDED + " DESC")
override fun onLoadFinished(loader: Loader<Cursor?>, data: Cursor?)
if (data != null)
var host = MkHost.getInstance().getCommonWapHost()
host = host.substring(0, host.length - 1)
val count = data.count
Log.e("xxx", "照片分类开始")
albumnList.clear()
allPicList?.clear()
if (count > 0)
data.moveToFirst()
do
//第一步:imageId,第二步:获取thumUri 第三步:获取缩略图
val image = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[0]))
val name = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[1]))
val imageId = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[2]))
// val thumbUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageId)
// Log.e("xxx-", "thumUri = " + thumbUri)
// Load thumbnail of a specific media item.
// val thumbnail: Bitmap? =
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
// contentResolver.loadThumbnail(thumbUri, Size(240, 480), null)
// else
// null
//
val path = File(image).parentFile.absolutePath
if (!albumnList.containsKey(path))
val albumBeanDefault = AlbumBean()
albumBeanDefault.albumId = ""
albumBeanDefault.count = count.toLong()
albumBeanDefault.name = "所有照片"
albumBeanDefault.image = image
albumnList["所有照片"] = albumBeanDefault
val albumBean = AlbumBean()
albumBean.albumId = path
albumBean.count = 1
albumBean.name = path.substring(path.lastIndexOf("/") + 1, path.length)
albumBean.image = image
Log.e("xxx-创建相册", albumBean.name)
albumnList[path] = albumBean
else
albumnList[path]?.count = albumnList[path]?.count!! + 1
//将相册照片分类
albumnList[path]?.images?.add(ImageBean(image, image))
Log.e("xxx-相册", albumnList[path]?.name + "添加相片" + image)
allPicList?.add(ImageBean(host + image, image))
while (data.moveToNext())
Log.e("xxx", "照片分类结束")
var onlyAlbumBean: OnlyAlbumBean? = null
onlyAblumnList.clear()
albumnList.forEach
onlyAlbumBean = OnlyAlbumBean(it.value.name, it.value.albumId, it.value.count, it.value.image)
onlyAblumnList.add(onlyAlbumBean!!)
val js = "window.$callbackStr($mGson.toJson(onlyAblumnList))"
Log.e("xxx-AlbumList", js)
runOnUiThread
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
wv_editor.evaluateJavascript(js, null)
override fun onLoaderReset(loader: Loader<Cursor?>)
if (albumnList == null || albumnList.size == 0)
mHandler?.post
supportLoaderManager.initLoader(0, null, mLoaderCallback)
else
var onlyAlbumBean: OnlyAlbumBean? = null
albumnList.forEach
onlyAlbumBean = OnlyAlbumBean(it.value.name, it.value.albumId, it.value.count, it.value.image)
onlyAblumnList.add(onlyAlbumBean!!)
val js = "window.$callbackStr($mGson.toJson(onlyAblumnList))"
Log.e("xxx-AlbumList", js)
runOnUiThread
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
wv_editor.evaluateJavascript(js, null)
"HOPhotoList" ->
Log.e("xxx", "HOPhotoList")
val callbackStr = object1.jsCbFnName ?: ""
val type2 = object : TypeToken<PhotoBean>() .type
val object2 = mGson.fromJson<PhotoBean>(object1.params, type2)
var start = object2.start
var limit = object2.limit
var albumn = object2.albumId
if (ContextCompat.checkSelfPermission(this@NetEditorActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE) !== PackageManager.PERMISSION_GRANTED)
ActivityCompat.requestPermissions(this@NetEditorActivity, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE), REQUEST_LIST_CODE)
else
Log.e("xxx-", "获取图片列表开始:" + System.currentTimeMillis())
var tempList: ArrayList<ImageBean>? = null
tempList = getPhotoListNew(start, limit, albumn ?: "")
// var list = BitmapUtils.getAllPicturesThumnail(this@NetEditorActivity)
// BitmapUtils.getThumnailList(this@NetEditorActivity)
var response: StringBuffer = StringBuffer()
response.append("[")
tempList?.forEachIndexed index, imageBean ->
response.append("\\"image\\":")
response.append("\\"$imageBean.image\\",")
response.append("\\"assetId\\":")
response.append("\\"$imageBean.assetId\\"")
response.append("")
if (index < tempList.size - 1)
response.append(",")
response.append("]")
val js = "window.$callbackStr($response)"
Log.e("xxx-", "获取图片列表结束:" + System.currentTimeMillis())
Log.e("xxx-", js)
runOnUiThread
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
wv_editor.evaluateJavascript(js, null)
"HOPhotoSelected" ->
val callbackStr = object1.jsCbFnName ?: ""
val type2 = object : TypeToken<SelectedPhotoBean>() .type
val object2 = mGson.fromJson<SelectedPhotoBean>(object1.params, type2)
var file = File(object2.assetId)
var fileInputStream = FileInputStream(file)
var response = ""
if (object2.assetId != null)
response = "data:image/jpeg;base64," + fileBase64String(object2.assetId!!)
val js = "window.$callbackStr(\\"originData\\":\\"$response\\")"
Log.e("xxx-", "获取图片列表结束:" + System.currentTimeMillis())
Log.e("xxx-", js)
runOnUiThread
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
wv_editor.evaluateJavascript(js, null)
"HOAlbumAuthStatus" ->
val granted = if (PermissionsManager.getInstance().hasAllPermissions(this@NetEditorActivity, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE))) 1 else 0
val callbackStr = object1.jsCbFnName ?: ""
val js = "window.$callbackStr(\\"authorized\\":\\"$granted.toString()\\")"
runOnUiThread
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
wv_editor.evaluateJavascript(js, null)
"HOAlbumAuthSetting" ->
PermissionsManager.getInstance().requestPermissionsIfNecessaryForResult(this@NetEditorActivity, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
object : PermissionsResultAction()
override fun onGranted()
val callbackStr = object1.jsCbFnName ?: ""
val js = "window.$callbackStr(\\"authorized\\":\\"1\\")"
runOnUiThread
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
wv_editor.evaluateJavascript(js, null)
以上是关于Android辅助H5做一个Web版的相册功能的主要内容,如果未能解决你的问题,请参考以下文章
Android-混合开发H5 能直接调起原生的相册和相机吗?