Add migration
- Fix some compile warnings - Add migration method - Add vmessBean migration
This commit is contained in:
@@ -3,7 +3,6 @@ package com.v2ray.ang
|
||||
import android.support.multidex.MultiDexApplication
|
||||
import android.support.v7.preference.PreferenceManager
|
||||
import com.tencent.mmkv.MMKV
|
||||
import com.v2ray.ang.util.AngConfigManager
|
||||
|
||||
class AngApplication : MultiDexApplication() {
|
||||
companion object {
|
||||
@@ -25,7 +24,6 @@ class AngApplication : MultiDexApplication() {
|
||||
defaultSharedPreferences.edit().putInt(PREF_LAST_VERSION, BuildConfig.VERSION_CODE).apply()
|
||||
|
||||
//Logger.init().logLevel(if (BuildConfig.DEBUG) LogLevel.FULL else LogLevel.NONE)
|
||||
AngConfigManager.inject(this)
|
||||
MMKV.initialize(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ inline fun Context.toast(message: CharSequence): Toast = ToastCompat
|
||||
show()
|
||||
}
|
||||
|
||||
fun JSONObject.putOpt(pair: Pair<String, Any>) = putOpt(pair.first, pair.second)!!
|
||||
fun JSONObject.putOpt(pair: Pair<String, Any>) = putOpt(pair.first, pair.second)
|
||||
fun JSONObject.putOpt(pairs: Map<String, Any>) = pairs.forEach { putOpt(it.key to it.value) }
|
||||
|
||||
const val threshold = 1000
|
||||
|
||||
@@ -1,199 +0,0 @@
|
||||
package com.v2ray.ang.ui
|
||||
|
||||
import android.app.ActivityOptions
|
||||
import android.app.FragmentManager
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.NavigationView
|
||||
import android.support.v4.view.GravityCompat
|
||||
import android.support.v4.widget.DrawerLayout
|
||||
import android.support.v7.app.ActionBarDrawerToggle
|
||||
import android.support.v7.widget.Toolbar
|
||||
import android.util.Log
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import com.v2ray.ang.R
|
||||
|
||||
abstract class BaseDrawerActivity : BaseActivity() {
|
||||
companion object {
|
||||
|
||||
private val TAG = "BaseDrawerActivity"
|
||||
}
|
||||
|
||||
private var mToolbar: Toolbar? = null
|
||||
|
||||
private var mDrawerToggle: ActionBarDrawerToggle? = null
|
||||
|
||||
private var mDrawerLayout: DrawerLayout? = null
|
||||
|
||||
private var mToolbarInitialized: Boolean = false
|
||||
|
||||
private var mItemToOpenWhenDrawerCloses = -1
|
||||
|
||||
private val backStackChangedListener = FragmentManager.OnBackStackChangedListener { updateDrawerToggle() }
|
||||
|
||||
private val drawerListener = object : DrawerLayout.DrawerListener {
|
||||
override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
|
||||
mDrawerToggle!!.onDrawerSlide(drawerView, slideOffset)
|
||||
}
|
||||
|
||||
override fun onDrawerOpened(drawerView: View) {
|
||||
mDrawerToggle!!.onDrawerOpened(drawerView)
|
||||
//supportActionBar!!.setTitle(R.string.app_name)
|
||||
}
|
||||
|
||||
override fun onDrawerClosed(drawerView: View) {
|
||||
mDrawerToggle!!.onDrawerClosed(drawerView)
|
||||
|
||||
if (mItemToOpenWhenDrawerCloses >= 0) {
|
||||
val extras = ActivityOptions.makeCustomAnimation(
|
||||
this@BaseDrawerActivity, R.anim.fade_in, R.anim.fade_out).toBundle()
|
||||
var activityClass: Class<*>? = null
|
||||
when (mItemToOpenWhenDrawerCloses) {
|
||||
R.id.sub_setting -> activityClass = SubSettingActivity::class.java
|
||||
R.id.settings -> activityClass = SettingsActivity::class.java
|
||||
R.id.logcat -> {
|
||||
startActivity(Intent(this@BaseDrawerActivity, LogcatActivity::class.java))
|
||||
return
|
||||
}
|
||||
R.id.donate -> {
|
||||
// startActivity<InappBuyActivity>()
|
||||
return
|
||||
}
|
||||
}
|
||||
if (activityClass != null) {
|
||||
startActivity(Intent(this@BaseDrawerActivity, activityClass), extras)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDrawerStateChanged(newState: Int) {
|
||||
mDrawerToggle!!.onDrawerStateChanged(newState)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
Log.d(TAG, "Activity onCreate")
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
if (!mToolbarInitialized) {
|
||||
throw IllegalStateException("You must run super.initializeToolbar at " + "the end of your onCreate method")
|
||||
}
|
||||
}
|
||||
|
||||
public override fun onResume() {
|
||||
super.onResume()
|
||||
// Whenever the fragment back stack changes, we may need to update the
|
||||
// action bar toggle: only top level screens show the hamburger-like icon, inner
|
||||
// screens - either Activities or fragments - show the "Up" icon instead.
|
||||
fragmentManager.addOnBackStackChangedListener(backStackChangedListener)
|
||||
}
|
||||
|
||||
public override fun onPause() {
|
||||
super.onPause()
|
||||
fragmentManager.removeOnBackStackChangedListener(backStackChangedListener)
|
||||
}
|
||||
|
||||
override fun onPostCreate(savedInstanceState: Bundle?) {
|
||||
super.onPostCreate(savedInstanceState)
|
||||
mDrawerToggle!!.syncState()
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
mDrawerToggle!!.onConfigurationChanged(newConfig)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (mDrawerToggle != null && mDrawerToggle!!.onOptionsItemSelected(item)) {
|
||||
return true
|
||||
}
|
||||
// If not handled by drawerToggle, home needs to be handled by returning to previous
|
||||
if (item.itemId == android.R.id.home) {
|
||||
onBackPressed()
|
||||
return true
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
// If the drawer is open, back will close it
|
||||
if (mDrawerLayout != null && mDrawerLayout!!.isDrawerOpen(GravityCompat.START)) {
|
||||
mDrawerLayout!!.closeDrawers()
|
||||
return
|
||||
}
|
||||
// Otherwise, it may return to the previous fragment stack
|
||||
val fragmentManager = fragmentManager
|
||||
if (fragmentManager.backStackEntryCount > 0) {
|
||||
fragmentManager.popBackStack()
|
||||
} else {
|
||||
// Lastly, it will rely on the system behavior for back
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateDrawerToggle() {
|
||||
if (mDrawerToggle == null) {
|
||||
return
|
||||
}
|
||||
val isRoot = fragmentManager.backStackEntryCount == 0
|
||||
mDrawerToggle!!.isDrawerIndicatorEnabled = isRoot
|
||||
|
||||
supportActionBar!!.setDisplayShowHomeEnabled(!isRoot)
|
||||
supportActionBar!!.setDisplayHomeAsUpEnabled(!isRoot)
|
||||
supportActionBar!!.setHomeButtonEnabled(!isRoot)
|
||||
|
||||
if (isRoot) {
|
||||
mDrawerToggle!!.syncState()
|
||||
}
|
||||
}
|
||||
|
||||
protected fun initializeToolbar() {
|
||||
mToolbar = findViewById<View>(R.id.toolbar) as Toolbar
|
||||
if (mToolbar == null) {
|
||||
throw IllegalStateException("Layout is required to include a Toolbar with id " + "'toolbar'")
|
||||
}
|
||||
|
||||
// mToolbar.inflateMenu(R.menu.main);
|
||||
|
||||
mDrawerLayout = findViewById<View>(R.id.drawer_layout) as DrawerLayout
|
||||
if (mDrawerLayout != null) {
|
||||
val navigationView = findViewById<View>(R.id.nav_view) as NavigationView
|
||||
?: throw IllegalStateException("Layout requires a NavigationView " + "with id 'nav_view'")
|
||||
|
||||
// Create an ActionBarDrawerToggle that will handle opening/closing of the drawer:
|
||||
mDrawerToggle = ActionBarDrawerToggle(this, mDrawerLayout,
|
||||
mToolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
|
||||
|
||||
mDrawerLayout!!.addDrawerListener(drawerListener)
|
||||
|
||||
populateDrawerItems(navigationView)
|
||||
setSupportActionBar(mToolbar)
|
||||
updateDrawerToggle()
|
||||
} else {
|
||||
setSupportActionBar(mToolbar)
|
||||
}
|
||||
|
||||
mToolbarInitialized = true
|
||||
}
|
||||
|
||||
private fun populateDrawerItems(navigationView: NavigationView) {
|
||||
navigationView.setNavigationItemSelectedListener { menuItem ->
|
||||
menuItem.isChecked = true
|
||||
mItemToOpenWhenDrawerCloses = menuItem.itemId
|
||||
mDrawerLayout!!.closeDrawers()
|
||||
true
|
||||
}
|
||||
|
||||
if (SubSettingActivity::class.java.isAssignableFrom(javaClass)) {
|
||||
navigationView.setCheckedItem(R.id.sub_setting)
|
||||
} else if (SettingsActivity::class.java.isAssignableFrom(javaClass)) {
|
||||
navigationView.setCheckedItem(R.id.settings)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,6 +100,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
version.text = "v${BuildConfig.VERSION_NAME} (${Libv2ray.checkVersionX()})"
|
||||
|
||||
setupViewModelObserver()
|
||||
migrateLegacy()
|
||||
}
|
||||
|
||||
private fun setupViewModelObserver() {
|
||||
@@ -129,6 +130,22 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
mainViewModel.startListenBroadcast()
|
||||
}
|
||||
|
||||
private fun migrateLegacy() {
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
val result = AngConfigManager.migrateLegacyConfig(this@MainActivity)
|
||||
if (result != null) {
|
||||
launch(Dispatchers.Main) {
|
||||
if (result) {
|
||||
toast(getString(R.string.migration_success))
|
||||
mainViewModel.reloadServerList()
|
||||
} else {
|
||||
toast(getString(R.string.migration_fail))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun startV2Ray() {
|
||||
if (mainStorage?.decodeString(MmkvManager.KEY_SELECTED_SERVER).isNullOrEmpty()) {
|
||||
return
|
||||
@@ -229,7 +246,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
}
|
||||
|
||||
R.id.export_all -> {
|
||||
if (AngConfigManager.shareNonCustomConfigsToClipboard(mainViewModel.serverList) == 0) {
|
||||
if (AngConfigManager.shareNonCustomConfigsToClipboard(this, mainViewModel.serverList) == 0) {
|
||||
toast(R.string.toast_success)
|
||||
} else {
|
||||
toast(R.string.toast_failure)
|
||||
|
||||
@@ -92,7 +92,7 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
|
||||
}
|
||||
}
|
||||
1 -> {
|
||||
if (AngConfigManager.share2Clipboard(guid) == 0) {
|
||||
if (AngConfigManager.share2Clipboard(mActivity, guid) == 0) {
|
||||
mActivity.toast(R.string.toast_success)
|
||||
} else {
|
||||
mActivity.toast(R.string.toast_failure)
|
||||
@@ -156,7 +156,7 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
|
||||
}
|
||||
|
||||
private fun shareFullContent(guid: String) {
|
||||
if (AngConfigManager.shareFullContent2Clipboard(guid) == 0) {
|
||||
if (AngConfigManager.shareFullContent2Clipboard(mActivity, guid) == 0) {
|
||||
mActivity.toast(R.string.toast_success)
|
||||
} else {
|
||||
mActivity.toast(R.string.toast_failure)
|
||||
|
||||
@@ -138,12 +138,12 @@ class PerAppProxyActivity : BaseActivity() {
|
||||
}
|
||||
})
|
||||
|
||||
switch_per_app_proxy.setOnCheckedChangeListener { buttonView, isChecked ->
|
||||
switch_per_app_proxy.setOnCheckedChangeListener { _, isChecked ->
|
||||
defaultSharedPreferences.edit().putBoolean(AppConfig.PREF_PER_APP_PROXY, isChecked).apply()
|
||||
}
|
||||
switch_per_app_proxy.isChecked = defaultSharedPreferences.getBoolean(AppConfig.PREF_PER_APP_PROXY, false)
|
||||
|
||||
switch_bypass_apps.setOnCheckedChangeListener { buttonView, isChecked ->
|
||||
switch_bypass_apps.setOnCheckedChangeListener { _, isChecked ->
|
||||
defaultSharedPreferences.edit().putBoolean(AppConfig.PREF_BYPASS_APPS, isChecked).apply()
|
||||
}
|
||||
switch_bypass_apps.isChecked = defaultSharedPreferences.getBoolean(AppConfig.PREF_BYPASS_APPS, false)
|
||||
|
||||
@@ -42,8 +42,8 @@ class RoutingSettingsFragment : Fragment() {
|
||||
return fragment
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val content = defaultSharedPreferences.getString(arguments!!.getString(routing_arg), "")
|
||||
et_routing_content.text = Utils.getEditable(content!!)
|
||||
|
||||
@@ -23,8 +23,8 @@ class ScannerActivity : BaseActivity(), ZXingScannerView.ResultHandler {
|
||||
|
||||
private var mScannerView: ZXingScannerView? = null
|
||||
|
||||
public override fun onCreate(state: Bundle?) {
|
||||
super.onCreate(state)
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
mScannerView = ZXingScannerView(this) // Programmatically initialize the scanner view
|
||||
|
||||
mScannerView?.setAutoFocus(true)
|
||||
|
||||
@@ -79,12 +79,10 @@ class TaskerActivity : BaseActivity() {
|
||||
val intent = Intent()
|
||||
|
||||
val remarks = lstData[position]
|
||||
var blurb = ""
|
||||
|
||||
if (switch_start_service.isChecked) {
|
||||
blurb = "Start $remarks"
|
||||
val blurb = if (switch_start_service.isChecked) {
|
||||
"Start $remarks"
|
||||
} else {
|
||||
blurb = "Stop $remarks"
|
||||
"Stop $remarks"
|
||||
}
|
||||
|
||||
intent.putExtra(AppConfig.TASKER_EXTRA_BUNDLE, extraBundle)
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package com.v2ray.ang.util
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.graphics.Bitmap
|
||||
import android.support.v7.preference.PreferenceManager
|
||||
import android.text.TextUtils
|
||||
import com.google.gson.Gson
|
||||
import com.tencent.mmkv.MMKV
|
||||
import com.v2ray.ang.AngApplication
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.AppConfig.ANG_CONFIG
|
||||
import com.v2ray.ang.AppConfig.HTTPS_PROTOCOL
|
||||
import com.v2ray.ang.AppConfig.HTTP_PROTOCOL
|
||||
@@ -19,43 +21,139 @@ import java.net.URLDecoder
|
||||
import java.util.*
|
||||
|
||||
object AngConfigManager {
|
||||
private lateinit var app: AngApplication
|
||||
private lateinit var angConfig: AngConfig
|
||||
private val mainStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_MAIN, MMKV.MULTI_PROCESS_MODE) }
|
||||
private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) }
|
||||
|
||||
fun inject(app: AngApplication) {
|
||||
this.app = app
|
||||
loadConfig()
|
||||
}
|
||||
private val subStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SUB, MMKV.MULTI_PROCESS_MODE) }
|
||||
|
||||
/**
|
||||
* loading config
|
||||
* Legacy loading config
|
||||
*/
|
||||
private fun loadConfig() {
|
||||
fun migrateLegacyConfig(c: Context): Boolean? {
|
||||
try {
|
||||
val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(app)
|
||||
val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(c)
|
||||
val context = defaultSharedPreferences.getString(ANG_CONFIG, "")
|
||||
if (!TextUtils.isEmpty(context)) {
|
||||
angConfig = Gson().fromJson(context, AngConfig::class.java)
|
||||
} else {
|
||||
angConfig = AngConfig(0, vmess = arrayListOf(AngConfig.VmessBean()), subItem = arrayListOf(AngConfig.SubItemBean()))
|
||||
angConfig.index = -1
|
||||
angConfig.vmess.clear()
|
||||
angConfig.subItem.clear()
|
||||
if (context.isNullOrBlank()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val angConfig = Gson().fromJson(context, AngConfig::class.java)
|
||||
for (i in angConfig.vmess.indices) {
|
||||
upgradeServerVersion(angConfig.vmess[i])
|
||||
}
|
||||
|
||||
// if (configs.subItem == null) {
|
||||
// configs.subItem = arrayListOf(AngConfig.SubItemBean())
|
||||
// }
|
||||
copyLegacySettings(defaultSharedPreferences)
|
||||
migrateVmessBean(angConfig, defaultSharedPreferences)
|
||||
migrateSubItemBean(angConfig)
|
||||
|
||||
defaultSharedPreferences.edit().remove(ANG_CONFIG).apply()
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun copyLegacySettings(sharedPreferences: SharedPreferences) {
|
||||
listOf(AppConfig.PREF_MODE,
|
||||
AppConfig.PREF_REMOTE_DNS,
|
||||
AppConfig.PREF_DOMESTIC_DNS,
|
||||
// AppConfig.PREF_LOCAL_DNS_PORT,
|
||||
// AppConfig.PREF_SOCKS_PORT,
|
||||
// AppConfig.PREF_HTTP_PORT,
|
||||
// AppConfig.PREF_LOGLEVEL,
|
||||
AppConfig.PREF_ROUTING_DOMAIN_STRATEGY,
|
||||
AppConfig.PREF_ROUTING_MODE,
|
||||
AppConfig.PREF_V2RAY_ROUTING_AGENT,
|
||||
AppConfig.PREF_V2RAY_ROUTING_BLOCKED,
|
||||
AppConfig.PREF_V2RAY_ROUTING_DIRECT,).forEach { key ->
|
||||
settingsStorage?.encode(key, sharedPreferences.getString(key, ""))
|
||||
}
|
||||
listOf(AppConfig.PREF_SPEED_ENABLED,
|
||||
AppConfig.PREF_SNIFFING_ENABLED,
|
||||
AppConfig.PREF_PROXY_SHARING,
|
||||
AppConfig.PREF_LOCAL_DNS_ENABLED,
|
||||
// AppConfig.PREF_ALLOW_INSECURE,
|
||||
// AppConfig.PREF_PREFER_IPV6,
|
||||
AppConfig.PREF_PER_APP_PROXY,
|
||||
AppConfig.PREF_BYPASS_APPS,).forEach { key ->
|
||||
settingsStorage?.encode(key, sharedPreferences.getBoolean(key, false))
|
||||
}
|
||||
settingsStorage?.encode(AppConfig.PREF_PER_APP_PROXY_SET, sharedPreferences.getStringSet(AppConfig.PREF_PER_APP_PROXY_SET, setOf()))
|
||||
}
|
||||
|
||||
private fun migrateVmessBean(angConfig: AngConfig, sharedPreferences: SharedPreferences) {
|
||||
angConfig.vmess.forEachIndexed { index, vmessBean ->
|
||||
val type = EConfigType.fromInt(vmessBean.configType) ?: return@forEachIndexed
|
||||
val config = ServerConfig.create(type)
|
||||
config.remarks = vmessBean.remarks
|
||||
config.subscriptionId = vmessBean.subid
|
||||
if (type == EConfigType.CUSTOM) {
|
||||
val jsonConfig = sharedPreferences.getString(ANG_CONFIG + vmessBean.guid, "")
|
||||
val v2rayConfig = try {
|
||||
Gson().fromJson(jsonConfig, V2rayConfig::class.java)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
return@forEachIndexed
|
||||
}
|
||||
config.fullConfig = v2rayConfig
|
||||
} else {
|
||||
config.outboundBean?.settings?.vnext?.get(0)?.let { vnext ->
|
||||
vnext.address = vmessBean.address
|
||||
vnext.port = vmessBean.port
|
||||
vnext.users[0].id = vmessBean.id
|
||||
if (config.configType == EConfigType.VMESS) {
|
||||
vnext.users[0].alterId = vmessBean.alterId
|
||||
vnext.users[0].security = vmessBean.security
|
||||
} else if (config.configType == EConfigType.VLESS) {
|
||||
vnext.users[0].encryption = vmessBean.security
|
||||
// vnext.users[0].flow = vmessBean.flow
|
||||
}
|
||||
}
|
||||
config.outboundBean?.settings?.servers?.get(0)?.let { server ->
|
||||
server.address = vmessBean.address
|
||||
server.port = vmessBean.port
|
||||
if (config.configType == EConfigType.SHADOWSOCKS) {
|
||||
server.password = vmessBean.id
|
||||
server.method = vmessBean.security
|
||||
} else if (config.configType == EConfigType.SOCKS) {
|
||||
if (TextUtils.isEmpty(vmessBean.security) && TextUtils.isEmpty(vmessBean.id)) {
|
||||
server.users = null
|
||||
} else {
|
||||
val socksUsersBean = V2rayConfig.OutboundBean.OutSettingsBean.ServersBean.SocksUsersBean()
|
||||
socksUsersBean.user = vmessBean.security
|
||||
socksUsersBean.pass = vmessBean.id
|
||||
server.users = listOf(socksUsersBean)
|
||||
}
|
||||
} else if (config.configType == EConfigType.TROJAN) {
|
||||
server.password = vmessBean.id
|
||||
}
|
||||
}
|
||||
config.outboundBean?.streamSettings?.let { streamSetting ->
|
||||
val sni = streamSetting.populateTransportSettings(vmessBean.network, vmessBean.headerType,
|
||||
vmessBean.requestHost, vmessBean.path, vmessBean.path, vmessBean.requestHost, vmessBean.path)
|
||||
// val allowInsecure = if (vmessBean.allowInsecure.isBlank()) {
|
||||
// settingsStorage?.decodeBool(AppConfig.PREF_ALLOW_INSECURE) ?: false
|
||||
// } else {
|
||||
// vmessBean.allowInsecure.toBoolean()
|
||||
// }
|
||||
streamSetting.populateTlsSettings(vmessBean.streamSecurity, false,
|
||||
sni)//if (vmessBean.sni.isNotBlank()) vmessBean.sni else sni)
|
||||
}
|
||||
}
|
||||
val key = MmkvManager.encodeServerConfig(vmessBean.guid, config)
|
||||
if (index == angConfig.index) {
|
||||
mainStorage?.encode(KEY_SELECTED_SERVER, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateSubItemBean(angConfig: AngConfig) {
|
||||
angConfig.subItem.forEach {
|
||||
val subItem = SubscriptionItem()
|
||||
subItem.remarks = it.remarks
|
||||
subItem.url = it.url
|
||||
//subItem.enabled = it.enabled
|
||||
subStorage?.encode(it.id, Gson().toJson(subItem))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -437,14 +535,14 @@ object AngConfigManager {
|
||||
/**
|
||||
* share2Clipboard
|
||||
*/
|
||||
fun share2Clipboard(guid: String): Int {
|
||||
fun share2Clipboard(context: Context, guid: String): Int {
|
||||
try {
|
||||
val conf = shareConfig(guid)
|
||||
if (TextUtils.isEmpty(conf)) {
|
||||
return -1
|
||||
}
|
||||
|
||||
Utils.setClipboard(app.applicationContext, conf)
|
||||
Utils.setClipboard(context, conf)
|
||||
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
@@ -456,7 +554,7 @@ object AngConfigManager {
|
||||
/**
|
||||
* share2Clipboard
|
||||
*/
|
||||
fun shareNonCustomConfigsToClipboard(serverList: List<String>): Int {
|
||||
fun shareNonCustomConfigsToClipboard(context: Context, serverList: List<String>): Int {
|
||||
try {
|
||||
val sb = StringBuilder()
|
||||
for (guid in serverList) {
|
||||
@@ -468,7 +566,7 @@ object AngConfigManager {
|
||||
sb.appendLine()
|
||||
}
|
||||
if (sb.count() > 0) {
|
||||
Utils.setClipboard(app.applicationContext, sb.toString())
|
||||
Utils.setClipboard(context, sb.toString())
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
@@ -497,12 +595,12 @@ object AngConfigManager {
|
||||
/**
|
||||
* shareFullContent2Clipboard
|
||||
*/
|
||||
fun shareFullContent2Clipboard(guid: String?): Int {
|
||||
fun shareFullContent2Clipboard(context: Context, guid: String?): Int {
|
||||
try {
|
||||
if (guid == null) return -1
|
||||
val result = V2rayConfigUtil.getV2rayConfig(app, guid)
|
||||
val result = V2rayConfigUtil.getV2rayConfig(context, guid)
|
||||
if (result.status) {
|
||||
Utils.setClipboard(app.applicationContext, result.content)
|
||||
Utils.setClipboard(context, result.content)
|
||||
} else {
|
||||
return -1
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ object AppManagerUtil {
|
||||
return apps
|
||||
}
|
||||
|
||||
fun rxLoadNetworkAppList(ctx: Context): Observable<ArrayList<AppInfo>> = Observable.create {
|
||||
fun rxLoadNetworkAppList(ctx: Context): Observable<ArrayList<AppInfo>> = Observable.unsafeCreate {
|
||||
it.onNext(loadNetworkAppList(ctx))
|
||||
}
|
||||
|
||||
|
||||
@@ -258,7 +258,7 @@ object Utils {
|
||||
*/
|
||||
fun isValidUrl(value: String?): Boolean {
|
||||
try {
|
||||
if (Patterns.WEB_URL.matcher(value).matches() || URLUtil.isValidUrl(value)) {
|
||||
if (value != null && Patterns.WEB_URL.matcher(value).matches() || URLUtil.isValidUrl(value)) {
|
||||
return true
|
||||
}
|
||||
} catch (e: WriterException) {
|
||||
|
||||
@@ -60,16 +60,16 @@ object V2rayConfigUtil {
|
||||
|
||||
//v2rayConfig.log.loglevel = settingsStorage?.decodeString(AppConfig.PREF_LOGLEVEL) ?: "warning"
|
||||
|
||||
inbounds(v2rayConfig, context)
|
||||
inbounds(v2rayConfig)
|
||||
|
||||
v2rayConfig.outbounds[0] = outbound
|
||||
|
||||
routing(v2rayConfig, context)
|
||||
routing(v2rayConfig)
|
||||
|
||||
if (settingsStorage?.decodeBool(AppConfig.PREF_LOCAL_DNS_ENABLED) == true) {
|
||||
customLocalDns(v2rayConfig, context)
|
||||
customLocalDns(v2rayConfig)
|
||||
} else {
|
||||
customRemoteDns(v2rayConfig, context)
|
||||
customRemoteDns(v2rayConfig)
|
||||
}
|
||||
if (settingsStorage?.decodeBool(AppConfig.PREF_SPEED_ENABLED) != true) {
|
||||
v2rayConfig.stats = null
|
||||
@@ -83,7 +83,7 @@ object V2rayConfigUtil {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private fun inbounds(v2rayConfig: V2rayConfig, context: Context): Boolean {
|
||||
private fun inbounds(v2rayConfig: V2rayConfig): Boolean {
|
||||
try {
|
||||
//val socksPort = Utils.parseInt(settingsStorage?.decodeString(AppConfig.PREF_SOCKS_PORT) ?: AppConfig.PORT_SOCKS)
|
||||
//val httpPort = Utils.parseInt(settingsStorage?.decodeString(AppConfig.PREF_HTTP_PORT) ?: AppConfig.PORT_HTTP)
|
||||
@@ -115,7 +115,7 @@ object V2rayConfigUtil {
|
||||
/**
|
||||
* routing
|
||||
*/
|
||||
private fun routing(v2rayConfig: V2rayConfig, context: Context): Boolean {
|
||||
private fun routing(v2rayConfig: V2rayConfig): Boolean {
|
||||
try {
|
||||
routingUserRule(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT) ?: "", AppConfig.TAG_AGENT, v2rayConfig)
|
||||
routingUserRule(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT) ?: "", AppConfig.TAG_DIRECT, v2rayConfig)
|
||||
@@ -233,7 +233,7 @@ object V2rayConfigUtil {
|
||||
/**
|
||||
* Custom Dns
|
||||
*/
|
||||
private fun customLocalDns(v2rayConfig: V2rayConfig, context: Context): Boolean {
|
||||
private fun customLocalDns(v2rayConfig: V2rayConfig): Boolean {
|
||||
try {
|
||||
val hosts = mutableMapOf<String, String>()
|
||||
val servers = ArrayList<Any>()
|
||||
@@ -342,7 +342,7 @@ object V2rayConfigUtil {
|
||||
/**
|
||||
* Custom Remote Dns
|
||||
*/
|
||||
private fun customRemoteDns(v2rayConfig: V2rayConfig, context: Context): Boolean {
|
||||
private fun customRemoteDns(v2rayConfig: V2rayConfig): Boolean {
|
||||
try {
|
||||
val servers = ArrayList<Any>()
|
||||
val hosts = mutableMapOf<String, String>()
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
<string name="app_tile_first_use">初次使用此功能请先用APP添加配置</string>
|
||||
<string name="navigation_drawer_open">Open navigation drawer</string>
|
||||
<string name="navigation_drawer_close">Close navigation drawer</string>
|
||||
<string name="migration_success">数据迁移成功!</string>
|
||||
<string name="migration_fail">数据迁移失败啦!</string>
|
||||
|
||||
<!-- Notifications -->
|
||||
<string name="notification_action_stop_v2ray">停止</string>
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
<string name="app_tile_first_use">首次使用此功能,請使用此應用程式新增組態</string>
|
||||
<string name="navigation_drawer_open">Open navigation drawer</string>
|
||||
<string name="navigation_drawer_close">Close navigation drawer</string>
|
||||
<string name="migration_success">數據遷移成功!</string>
|
||||
<string name="migration_fail">數據遷移失敗啦!</string>
|
||||
|
||||
<!-- Notifications -->
|
||||
<string name="notification_action_stop_v2ray">停止</string>
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
<string name="app_tile_first_use">First use of this feature, please use the app to add server</string>
|
||||
<string name="navigation_drawer_open">Open navigation drawer</string>
|
||||
<string name="navigation_drawer_close">Close navigation drawer</string>
|
||||
<string name="migration_success">Data migration success!</string>
|
||||
<string name="migration_fail">Data migration failed!</string>
|
||||
|
||||
<!-- Notifications -->
|
||||
<string name="notification_action_stop_v2ray">Stop</string>
|
||||
|
||||
Reference in New Issue
Block a user