yijianlianUI/app/src/main/java/com/yingmao/clash/act/SplashActivity.kt

698 lines
29 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.yingmao.clash.act
import android.annotation.SuppressLint
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.View
import android.view.WindowManager
import android.webkit.JavascriptInterface
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.Button
import android.widget.ProgressBar
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.core.content.FileProvider
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.afollestad.materialdialogs.MaterialDialog
import com.baidu.mobads.action.ActionType
import com.baidu.mobads.action.BaiduAction
import com.baidu.mobads.action.PrivacyStatus
import com.cncat.vpn.service.ClashManager
import com.cncat.vpn.service.remote.IClashManager
import com.cncat.vpn.service.remote.wrap
import com.github.gzuliyujiang.oaid.DeviceID
import com.github.gzuliyujiang.oaid.DeviceIdentifier
import com.google.gson.JsonObject
import com.tencent.mmkv.MMKV
import com.yingmao.clash.BuildConfig
import com.yingmao.clash.R
import com.yingmao.clash.app.MainApplication
import com.yingmao.clash.app.MainApplication.Companion.OAID
import com.yingmao.clash.base.BaseActivity
import com.yingmao.clash.conf.BZYConstants
import com.yingmao.clash.conf.BZYConstants.Companion.MMKV_KEY_IS_REGISTER
import com.yingmao.clash.conf.BZYConstants.Companion.MMKV_KEY_NOTE_DEFAULT_PSW
import com.yingmao.clash.conf.BZYConstants.Companion.MMKV_KEY_REMEMBER_PASSWORD
import com.yingmao.clash.conf.BZYConstants.Companion.MMKV_KEY_REMEMBER_USERNAME
import com.yingmao.clash.entity.CheckLoginRsp
import com.yingmao.clash.listener.DownLoadListener
import com.yingmao.clash.net.http.HttpReqType
import com.yingmao.clash.net.http.HttpStatus
import com.yingmao.clash.net.http.entity.AppVersionCheckRsp
import com.yingmao.clash.net.http.entity.LoginRsp
import com.yingmao.clash.net.http.entity.RegisterRsp
import com.yingmao.clash.util.AESUtil
import com.yingmao.clash.util.Utils
import com.yingmao.clash.view.RxToast
import com.yingmao.clash.view.dialog.DialogAppVersion
import com.yingmao.clash.view.dialog.DialogDoMainChoose
import com.yingmao.clash.view.dialog.SplashDialog
import com.yingmao.clash.vm.SplashAtyVM
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.io.File
import java.util.Locale
@SuppressLint("CustomSplashScreen")
class SplashActivity : BaseActivity() {
private lateinit var rlPb: View
private lateinit var llAction: View
private var butSkip: Button? = null
private var butRegister: Button? = null
private lateinit var rlMain: RelativeLayout
private var webView: WebView? = null
private lateinit var pbWeb: ProgressBar
private lateinit var splashAtyVM: SplashAtyVM
companion object {
var registerKey = ""
var registerIV2 = ""
lateinit var username: String
var InviteCode=""
}
private var captchaInfo = ""
private var initErrMsg = ""
override fun onCreate(savedInstanceState: Bundle?) {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
super.onCreate(savedInstanceState)
initErrMsg = resources.getString(R.string.splashErrorTips)
splashAtyVM = ViewModelProvider(this).get(SplashAtyVM::class.java)
observe(this, splashAtyVM)
setContentView(R.layout.layout_splash_activity)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.rlMain)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
rlMain = findViewById(R.id.rlMain)
rlPb = findViewById(R.id.rl_pb)
llAction = findViewById(R.id.ll_action)
webView = findViewById(R.id.webView)
pbWeb = findViewById(R.id.pb_web)
butSkip = findViewById(R.id.but_skip)
butRegister = findViewById(R.id.but_register)
val decodeBool =
MMKV.defaultMMKV().decodeBool(BZYConstants.is_splash_first, false)
if (!decodeBool) {
val splashDialog =
SplashDialog(this)
splashDialog.showDialog(this@SplashActivity)
splashDialog.setOnDialogClickListener(object : SplashDialog.ActivityLinkListener {
override fun onAgreeClickListener() {
MMKV.defaultMMKV().encode(BZYConstants.is_splash_first, true)
splashDialog.cancel()
rlPb.visibility = View.VISIBLE
initInto()
}
override fun onDisagreeClickListener() {
MMKV.defaultMMKV().encode(BZYConstants.is_splash_first, false)
splashDialog.cancel()
finish()
}
})
} else {
initInto()
}
}
private fun initInto() {
serStore.isYM = true
initApplication()
}
private fun initApplication() {
username = Utils.getUniqueID(this)
MainApplication.initUtil()
val oaId = OAID
Log.i("SplashActOAID","OAID::"+OAID+"oaId.isEmpty()::"+oaId.isEmpty())
if(oaId.isEmpty()){
if (DeviceID.supportedOAID(this)){
val aynOAID = DeviceIdentifier.getOAID(this)
OAID=aynOAID
BaiduAction.setOaid(aynOAID)
//设置同意隐私政策激活设备
BaiduAction.setPrivacyStatus(PrivacyStatus.AGREE)
}
}else{
BaiduAction.setOaid(oaId)
//设置同意隐私政策激活设备
BaiduAction.setPrivacyStatus(PrivacyStatus.AGREE)
}
setLocalLanguage()
val clashBinder = MainApplication.getApp()?.let {
ClashManager(it).wrap() as IClashManager
}
clashBinder?.let { cb ->
val signList =
AESUtil.getSingInfo(this@SplashActivity, BuildConfig.applicationId, AESUtil.SHA256)
if (signList.isNotEmpty()) {
val si = signList[0]
val ss1 = cb.getSS1(si)
val ss2 = cb.getSS2(si)
registerKey = cb.getRegisterKey(si)
registerIV2 = cb.getRegisterKiv(si)
MainApplication.KEY2 = ss1
MainApplication.IV2 = ss2
val routerSet =
MMKV.defaultMMKV().decodeStringSet(BZYConstants.MMKV_KEY_ROUTER_HOST)
if (routerSet != null && routerSet.isNotEmpty()) {
SplashHelper(splashAtyVM).getHostWithFallback { success ->
}
isNeedRegister(true)
} else {
if (BuildConfig.is_back_cn == true) { //没有备用域名所以无需调用getHost
isNeedRegister(true)
} else {
SplashHelper(splashAtyVM).getHostWithFallback { success ->
MainScope().launch {
if (success) {
isNeedRegister(true)
} else {
isNeedRegister(true)
}
}
}
}
}
}
}
// //对源地址加密操作
// val byteArrayToHexStr =
// AESUtil.byteArrayToHexStr(AESUtil.encrypt("https://api.yijianlianjsq.com+https://yjl.kuaifei.net+https://api.onetouchjsq.com+https://yjlapi.anxuan009.com+https://yjl.jimao.xyz"))
// android.util.Log.i("AAAAAAAAAAA","data:::"+byteArrayToHexStr)
}
@SuppressLint("JavascriptInterface", "SetJavaScriptEnabled")
private fun setWebView() {
rlPb.visibility = View.INVISIBLE
webView?.visibility = View.VISIBLE
lifecycleScope.launch(Dispatchers.Main) {
delay(3000) // 延迟3秒
com.cncat.vpn.common.log.Log.d("setWebView delay")
butSkip?.visibility = View.VISIBLE
butRegister?.visibility = View.VISIBLE
}
// WebView设置
val webSettings = webView?.settings
// 可选设置开启Chrome调试
WebView.setWebContentsDebuggingEnabled(true)
// 设置屏幕自适应
webSettings?.useWideViewPort = true
webSettings?.loadWithOverviewMode = true
// 建议禁止缓存加载以确保在攻击发生时可快速获取最新的阿里云验证码2.0进行对抗
webSettings?.cacheMode = WebSettings.LOAD_NO_CACHE
// 设置WebView组件支持加载JavaScript
webSettings?.javaScriptEnabled = true
webSettings?.domStorageEnabled = true
// 设置不使用默认浏览器而直接使用WebView组件加载页面
webView?.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
view.loadUrl(url)
return true
}
}
webView?.addJavascriptInterface(CaptchaJsInterface(), "CaptchaJsInterface")
// 加载业务页面
webView?.loadUrl("file:///android_asset/captcha.html")
}
inner class CaptchaJsInterface() {
@SuppressLint("ClickableViewAccessibility")
@JavascriptInterface
public fun getVerifyResult(verifyResult: String): Boolean {
com.cncat.vpn.common.log.Log.d("verifyResult==>${verifyResult}")
captchaInfo = verifyResult
launch {
webView?.setOnTouchListener { _, _ -> true }
pbWeb.visibility = View.VISIBLE
}
doRegisterByEncryption()
return true
}
}
private fun setLocalLanguage() {
val defLan = ""
val decodeString = MMKV.defaultMMKV().decodeString(BZYConstants.languageInfo, defLan)
if (!decodeString.isNullOrEmpty()) {
when (decodeString) {
"Chinese-CN" -> {
val config = resources.configuration
config.locale = Locale.CHINA
updateLanguage("Chinese-CN", Locale.CHINA)
}
"Chinese-HK" -> {
val config = resources.configuration
config.locale = Locale("zh", "HK")
updateLanguage("Chinese-HK", Locale("zh", "HK"))
}
"English" -> {
val config = resources.configuration
config.locale = Locale.ENGLISH
updateLanguage("English", Locale.ENGLISH)
}
}
}
}
private fun isNeedRegister(isNeedRegister: Boolean) {
if (!BuildConfig.is_free && BuildConfig.productId.isNotEmpty()) { //渠道包都自动注册登录广州22222也是非自动注册
if (MMKV.defaultMMKV().decodeBool(MMKV_KEY_IS_REGISTER, false)) {
rlPb.visibility = View.VISIBLE
butSkip?.visibility = View.INVISIBLE
butRegister?.visibility = View.INVISIBLE
splashAtyVM.checkLogin()
} else {
if (isNeedRegister) {
doRegisterByEncryption()
} else {
setWebView()
}
}
} else {//非渠道自由包
val token = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_TOKEN)
llAction.visibility = View.VISIBLE
rlPb.visibility = View.INVISIBLE
butSkip?.visibility = View.INVISIBLE
butRegister?.visibility = View.INVISIBLE
if (MMKV.defaultMMKV().decodeBool(MMKV_KEY_IS_REGISTER, false)) {
if (token != null && token.isNotEmpty()) {
llAction.visibility = View.GONE
rlPb.visibility = View.VISIBLE
splashAtyVM.checkLogin()
} else {
val intent = Intent(this@SplashActivity, LoginActivity::class.java)
startActivity(intent)
finish()
}
} else {
findViewById<View>(R.id.rl_action_login).setOnClickListener {//点有账号直接登录的
val intent = Intent(this@SplashActivity, LoginActivity::class.java)
startActivity(intent)
finish()
}
findViewById<View>(R.id.rl_action_register).setOnClickListener {//无账号的自动注册但不会填任何渠道号
val intent = Intent(this@SplashActivity, RegisterActivity::class.java)
startActivity(intent)
finish()
}
}
}
}
@Synchronized
fun doRegisterByEncryption() {
var userAgent = System.getProperty("http.agent")
Log.i("SplashRegister", "userAgent::$userAgent")
if (userAgent != null) {
if (userAgent.isEmpty() || userAgent.length < 5) {
val webView = WebView(this@SplashActivity)
userAgent = webView.settings.userAgentString
}
} else {
val webView = WebView(this@SplashActivity)
userAgent = webView.settings.userAgentString
}
var oaId = OAID
Log.i(
"SplashRegister",
"OAID::" + OAID + "oaId.isEmpty()::" + oaId.isEmpty() + "userAgent::" + userAgent
)
val equipmentModel = Utils.getEquipmentModel()
Log.i("equipmentModel", "equipmentModel::" + equipmentModel)
if (oaId.isEmpty()) {
if (DeviceID.supportedOAID(MainApplication.getApp())) {
//同步获取oaid
val aOaId = DeviceIdentifier.getOAID(MainApplication.getApp())
oaId = aOaId
OAID = aOaId
Log.i(
"doRegisterByEncryption",
"aOaId::" + aOaId + "oaId::" + oaId + "OAID::" + OAID
)
}
}
val reqJson = JsonObject()
reqJson.addProperty("password", BZYConstants.defaultPassword)
reqJson.addProperty("checkPassword", BZYConstants.defaultPassword)
reqJson.addProperty("invitationCode", BuildConfig.productId)
reqJson.addProperty("clientIp", "127.0.0.1")
reqJson.addProperty("from", "5")
reqJson.addProperty("androidDevice", username)
reqJson.addProperty("userAgent", userAgent)
reqJson.addProperty("oaid", oaId)
reqJson.addProperty("equipmentModel", equipmentModel)
reqJson.addProperty("pkg", BuildConfig.applicationId)
if (captchaInfo.isNotEmpty()) {
reqJson.addProperty("captchaVerifyParam", captchaInfo)
}
if (registerKey.isNotEmpty() && registerIV2.isNotEmpty()) {
val data = AESUtil.byteArrayToHexStr(
AESUtil.RegisterEncrypt(reqJson.toString(), registerKey, registerIV2)
)
val params: Map<String, String> = mutableMapOf(
"data" to data
)
splashAtyVM.registerByEncryption(params)
}
}
@SuppressLint("ClickableViewAccessibility")
override fun httpSuccess(httpStatus: HttpStatus.Success) {
when (httpStatus.reqType) {
HttpReqType.REGISTER -> {
dialogDoMainChoose?.dismiss()
with(httpStatus.rsp as RegisterRsp) {
if (code == "10000" || code == "200") {
if (data != null) {
if (!data.phoneNumber.isNullOrEmpty()) {
MMKV.defaultMMKV()
.encode(MMKV_KEY_REMEMBER_USERNAME, data.phoneNumber)
} else {
MMKV.defaultMMKV().encode(MMKV_KEY_REMEMBER_USERNAME, username)
}
} else {
MMKV.defaultMMKV().encode(MMKV_KEY_REMEMBER_USERNAME, username)
}
MMKV.defaultMMKV()
.encode(MMKV_KEY_REMEMBER_PASSWORD, BZYConstants.defaultPassword)
MMKV.defaultMMKV().encode(MMKV_KEY_IS_REGISTER, true)
MMKV.defaultMMKV().encode(MMKV_KEY_NOTE_DEFAULT_PSW, true)
val encryName = AESUtil.byteArrayToHexStr(
AESUtil.encrypt(data?.phoneNumber)
)
val encryPsw = AESUtil.byteArrayToHexStr(
AESUtil.encrypt(BZYConstants.defaultPassword)
)
val decodeBool =
MMKV.defaultMMKV().decodeBool(BZYConstants.INITIALIZATION, true)
if (decodeBool) {
MMKV.defaultMMKV().encode(BZYConstants.INITIALIZATION, true)
}
splashAtyVM.login(encryName, encryPsw)
} else if (code == "20062") {
message?.let {
RxToast.error(it)
}
if (data != null) {
if (!data.phoneNumber.isNullOrEmpty()) {
MMKV.defaultMMKV()
.encode(MMKV_KEY_REMEMBER_USERNAME, data.phoneNumber)
} else {
MMKV.defaultMMKV().encode(MMKV_KEY_REMEMBER_USERNAME, username)
}
} else {
MMKV.defaultMMKV().encode(MMKV_KEY_REMEMBER_USERNAME, username)
}
val intent = Intent(this@SplashActivity, LoginActivity::class.java)
startActivity(intent)
finish()
} else if (code == "403") {
pbWeb.visibility = View.INVISIBLE
message?.let {
RxToast.error(it)
}
webView?.setOnTouchListener { _, _ -> false }
} else {
MaterialDialog(this@SplashActivity).show {
message(text = initErrMsg)
positiveButton(R.string.retry) {
doRegisterByEncryption()
}
negativeButton(R.string.cancel) {
it.dismiss()
finish()
}
}
}
}
}
HttpReqType.LOGIN -> {
val rsp = httpStatus.rsp
if (rsp is LoginRsp) {
if (rsp.code == "1000") {
val mmkv = MMKV.defaultMMKV()
com.cncat.vpn.common.log.Log.i(" HttpReqType.LOGIN token ==> ${rsp.data.vpnToken}")
mmkv.encode(BZYConstants.MMKV_KEY_TOKEN, rsp.data.vpnToken)
mmkv.encode(BZYConstants.MMKV_KEY_PH_TOKEN, rsp.data.phToken)
mmkv.encode(BZYConstants.MMKV_KEY_USER_ID, rsp.data.userId)
splashAtyVM.checkLogin()
} else {
MaterialDialog(this@SplashActivity).show {
message(text = initErrMsg)
positiveButton(R.string.retry) {
val entryName = AESUtil.byteArrayToHexStr(
AESUtil.encrypt(username)
)
val entryPsw = AESUtil.byteArrayToHexStr(
AESUtil.encrypt(BZYConstants.defaultPassword)
)
splashAtyVM.login(entryName, entryPsw)
}
negativeButton(R.string.cancel) {
it.dismiss()
finish()
}
}
}
}
}
HttpReqType.CHECK_LOGIN -> {
dialogDoMainChoose?.dismiss()
(httpStatus.rsp as CheckLoginRsp).let { checkLoginRsp ->
if (checkLoginRsp.code == 0) {
com.cncat.vpn.common.log.Log.d("splash CHECK_LOGIN==>")
checkLoginRsp.data?.let { MainApplication.setUserInfo(it) }
val expired = checkLoginRsp.data?.expired
val isPerfect = checkLoginRsp.data?.isPerfect
val userCommand = checkLoginRsp.data?.userCommand
val logSwitch = checkLoginRsp.data?.logSwitch
val mmkv = MMKV.defaultMMKV()
mmkv.encode(BZYConstants.MMKV_KEY_VPN_EXPIRED, expired ?: true)
mmkv.encode(
BZYConstants.MMKV_KEY_VPN_VALID_PERIOD,
checkLoginRsp.data?.vpnExpireTime ?: 0
)
mmkv.encode(BZYConstants.MMKV_KEY_IS_PERFECT, isPerfect ?: true)
mmkv.encode(BZYConstants.MMKV_KEY_VPN_UserCommand, userCommand ?: "")
mmkv.encode(BZYConstants.MMKV_KEY_VPN_LogSwitch, logSwitch ?: "")
toMainPage()
} else {
toLoginPage()
}
}
}
HttpReqType.App_VERION_CHECK -> {
(httpStatus.rsp as AppVersionCheckRsp).let { avcr ->
com.cncat.vpn.common.log.Log.i("App_VERION_CHECK ==>$avcr")
if (avcr.code == 200) {
avcr.data?.let { md ->
if (md.isForce) { //强制更新
if (!TextUtils.isEmpty(md.versionPath)) {
showUpdateDialog(md.versionPath!!, md.illustrate!!, true)
}
} else if (md.isUpgrade) { //更新
if (!TextUtils.isEmpty(md.versionPath)) {
showUpdateDialog(md.versionPath!!, md.illustrate!!, false)
}
} else {
val intent =
Intent(this@SplashActivity, MainActivity::class.java)
startActivity(intent)
finish()
}
}
} else {
val intent = Intent(this@SplashActivity, MainActivity::class.java)
startActivity(intent)
finish()
}
}
}
else -> {}
}
}
var dialogDoMainChoose: DialogDoMainChoose? = null
override fun httpFailure(httpStatus: HttpStatus.Failure) {
when (httpStatus.reqType) {
HttpReqType.REGISTER -> {
rlPb.visibility = View.GONE
pbWeb.visibility = View.INVISIBLE
com.cncat.vpn.common.log.Log.d("httpFailure HttpReqType.REGISTER")
if (super.switchServer2()) {//切换服务器并直接重试
doRegisterByEncryption()
} else {
MaterialDialog(this@SplashActivity).show {
message(text = initErrMsg)
positiveButton(R.string.retry) {
doRegisterByEncryption()
}
negativeButton(R.string.cancel) {
it.dismiss()
finish()
}
}
}
}
HttpReqType.LOGIN -> {
MaterialDialog(this@SplashActivity).show {
message(text = initErrMsg)
positiveButton(R.string.confirm) {
val encryName = AESUtil.byteArrayToHexStr(
AESUtil.encrypt(username)
)
val encryPsw = AESUtil.byteArrayToHexStr(
AESUtil.encrypt(BZYConstants.defaultPassword)
)
splashAtyVM.login(encryName, encryPsw)
}
negativeButton(R.string.cancel) {
it.dismiss()
finish()
}
}
}
HttpReqType.CHECK_LOGIN -> {
com.cncat.vpn.common.log.Log.d("httpFailure HttpReqType.CHECK_LOGIN")
RxToast.error("检测到网络异常,请尝试切换其他地址.")
if (super.switchServer2()) {
splashAtyVM.checkLogin()
} else {
toLoginPage()
}
}
else -> {}
}
}
private fun toMainPage() {
//监测版本是否需要更新
splashAtyVM.appCheck()
}
private fun toLoginPage() {
val intent = Intent(this, LoginActivity::class.java)
startActivity(intent)
finish()
}
fun updateLanguage(language: String, locale: Locale) {
MMKV.defaultMMKV().encode(BZYConstants.languageInfo, language)
val resources = this.resources
val metrics = resources.displayMetrics
val config = resources.configuration
config.locale = locale
resources.updateConfiguration(config, metrics)
}
private fun showUpdateDialog(url: String, illustrate: String, isForce: Boolean) {
if (TextUtils.isEmpty(url)) {
RxToast.error(resources.getString(R.string.downloadEmpty))
return
}
var notice = illustrate
if (TextUtils.isEmpty(illustrate)) {
notice = resources.getString(R.string.NewVersion)
}
var isDownloaded = false;
var isFinish = false
var downFilePath = ""
val dialog = DialogAppVersion(
this,
notice,
url,
isForce,
object : DialogAppVersion.OnClickListener {
override fun ok(tv_down: TextView, pb_down: ProgressBar) {
if (isFinish) {
installApk(downFilePath)
return
}
if (isDownloaded) {
RxToast.info(resources.getString(R.string.downloading))
return
}
isDownloaded = true
splashAtyVM.downLoadFile(url, object : DownLoadListener {
@SuppressLint("SetTextI18n")
override fun loading(progress: Int) {
lifecycleScope.async {
pb_down.progress = progress
tv_down.text = resources.getString(R.string.download) + "$progress%"
}
}
override fun finish(path: String) {
com.cncat.vpn.common.log.Log.d("down finish path==>$path")
isFinish = true
downFilePath = path
installApk(path)
}
override fun error(msg: String) {
com.cncat.vpn.common.log.Log.d("down error msg==>$msg")
}
})
}
override fun cancel() {
val intent = Intent(this@SplashActivity, MainActivity::class.java)
startActivity(intent)
finish()
}
})
dialog.show()
}
fun installApk(filePath: String) {
val file = File(filePath)
val uri: Uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
FileProvider.getUriForFile(this, "${applicationContext.packageName}.fileprovider", file)
} else {
Uri.fromFile(file)
}
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(uri, "application/vnd.android.package-archive")
flags = Intent.FLAG_ACTIVITY_NEW_TASK
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
}
startActivity(intent)
}
}