mirror of
https://github.com/SagerNet/sing-box-for-android.git
synced 2025-03-31 10:27:38 +03:00
Replace appcenter with google services
This commit is contained in:
parent
0f9441c650
commit
446ffa4a4d
14 changed files with 182 additions and 187 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -8,4 +8,5 @@
|
|||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
/app/libs/
|
||||
/app/libs/
|
||||
/service-account-credentials.json
|
|
@ -5,6 +5,9 @@ plugins {
|
|||
id 'kotlin-android'
|
||||
id 'kotlin-parcelize'
|
||||
id 'com.google.devtools.ksp'
|
||||
id 'com.google.gms.google-services'
|
||||
id 'com.google.firebase.crashlytics'
|
||||
id 'com.github.triplet.play'
|
||||
}
|
||||
|
||||
android {
|
||||
|
@ -39,13 +42,15 @@ android {
|
|||
if (getProps("KEYSTORE_PASS") != "") {
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
buildConfigField("String", "APPCENTER_SECRET", "\"" + getProps("APPCENTER_SECRET") + "\"")
|
||||
}
|
||||
release {
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
signingConfig signingConfigs.release
|
||||
buildConfigField("String", "APPCENTER_SECRET", "\"" + getProps("APPCENTER_SECRET") + "\"")
|
||||
firebaseCrashlytics {
|
||||
nativeSymbolUploadEnabled true
|
||||
unstrippedNativeLibsDir true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,14 +101,14 @@ dependencies {
|
|||
implementation 'com.blacksquircle.ui:editorkit:2.2.0'
|
||||
implementation 'com.blacksquircle.ui:language-json:2.2.0'
|
||||
|
||||
implementation 'com.microsoft.appcenter:appcenter-analytics:5.0.2'
|
||||
implementation 'com.microsoft.appcenter:appcenter-crashes:5.0.2'
|
||||
implementation 'com.microsoft.appcenter:appcenter-distribute:5.0.2'
|
||||
|
||||
implementation('org.smali:dexlib2:2.5.2') {
|
||||
exclude group: 'com.google.guava', module: 'guava'
|
||||
}
|
||||
implementation('com.google.guava:guava:32.1.2-android')
|
||||
|
||||
implementation platform('com.google.firebase:firebase-bom:32.4.0')
|
||||
implementation 'com.google.firebase:firebase-crashlytics-ktx'
|
||||
implementation 'com.google.android.play:app-update-ktx:2.1.0'
|
||||
}
|
||||
|
||||
if (getProps("APPCENTER_TOKEN") != "") {
|
||||
|
@ -122,6 +127,15 @@ if (getProps("APPCENTER_TOKEN") != "") {
|
|||
}
|
||||
}
|
||||
|
||||
def playCredentialsJSON = rootProject.file("service-account-credentials.json")
|
||||
if (playCredentialsJSON.exists()) {
|
||||
play {
|
||||
serviceAccountCredentials = playCredentialsJSON
|
||||
defaultToAppBundles = true
|
||||
track = 'beta'
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(KotlinCompile.class).configureEach {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
|
|
29
app/google-services.json
Normal file
29
app/google-services.json
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"project_info": {
|
||||
"project_number": "548801210715",
|
||||
"project_id": "sing-b0x",
|
||||
"storage_bucket": "sing-b0x.appspot.com"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:548801210715:android:2c3bce07700eecb54d527e",
|
||||
"android_client_info": {
|
||||
"package_name": "io.nekohasekai.sfa"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyDzb5nuF2qyw-AW0opn4Ymi2QGuJ6dZyYo"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": []
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
|
@ -39,6 +39,10 @@
|
|||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/shortcuts" />
|
||||
|
||||
<meta-data
|
||||
android:name="firebase_crashlytics_collection_enabled"
|
||||
android:value="false" />
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
|
@ -173,11 +177,6 @@
|
|||
android:resource="@xml/cache_paths" />
|
||||
</provider>
|
||||
|
||||
|
||||
<receiver
|
||||
android:name="com.microsoft.appcenter.distribute.UpdateReceiver"
|
||||
tools:node="remove" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -4,7 +4,7 @@ object SettingsKey {
|
|||
|
||||
const val SELECTED_PROFILE = "selected_profile"
|
||||
const val SERVICE_MODE = "service_mode"
|
||||
const val ANALYTICS_ALLOWED = "analytics_allowed"
|
||||
const val ERROR_REPORTING_ENABLED = "error_reporting_enabled"
|
||||
const val CHECK_UPDATE_ENABLED = "check_update_enabled"
|
||||
const val DISABLE_MEMORY_LIMIT = "disable_memory_limit"
|
||||
|
||||
|
|
|
@ -38,11 +38,11 @@ object Settings {
|
|||
var serviceMode by dataStore.string(SettingsKey.SERVICE_MODE) { ServiceMode.NORMAL }
|
||||
var startedByUser by dataStore.boolean(SettingsKey.STARTED_BY_USER)
|
||||
|
||||
const val ANALYSIS_UNKNOWN = -1
|
||||
const val ANALYSIS_ALLOWED = 0
|
||||
const val ANALYSIS_DISALLOWED = 1
|
||||
const val ERROR_REPORTING_UNKNOWN = -1
|
||||
const val ERROR_REPORTING_ALLOWED = 0
|
||||
const val ERROR_REPORTING_DISALLOWED = 1
|
||||
|
||||
var analyticsAllowed by dataStore.int(SettingsKey.ANALYTICS_ALLOWED) { ANALYSIS_UNKNOWN }
|
||||
var errorReportingEnabled by dataStore.int(SettingsKey.ERROR_REPORTING_ENABLED) { ERROR_REPORTING_UNKNOWN }
|
||||
var checkUpdateEnabled by dataStore.boolean(SettingsKey.CHECK_UPDATE_ENABLED) { true }
|
||||
var disableMemoryLimit by dataStore.boolean(SettingsKey.DISABLE_MEMORY_LIMIT)
|
||||
|
||||
|
|
|
@ -2,12 +2,11 @@ package io.nekohasekai.sfa.ui
|
|||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.VpnService
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import androidx.activity.result.contract.ActivityResultContract
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.core.content.ContextCompat
|
||||
|
@ -18,18 +17,16 @@ import androidx.navigation.ui.AppBarConfiguration
|
|||
import androidx.navigation.ui.setupActionBarWithNavController
|
||||
import androidx.navigation.ui.setupWithNavController
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.microsoft.appcenter.AppCenter
|
||||
import com.microsoft.appcenter.analytics.Analytics
|
||||
import com.microsoft.appcenter.crashes.Crashes
|
||||
import com.microsoft.appcenter.distribute.Distribute
|
||||
import com.microsoft.appcenter.distribute.DistributeListener
|
||||
import com.microsoft.appcenter.distribute.ReleaseDetails
|
||||
import com.microsoft.appcenter.distribute.UpdateAction
|
||||
import com.microsoft.appcenter.utils.AppNameHelper
|
||||
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
|
||||
import com.google.android.play.core.appupdate.AppUpdateOptions
|
||||
import com.google.android.play.core.install.model.AppUpdateType
|
||||
import com.google.android.play.core.install.model.InstallStatus
|
||||
import com.google.android.play.core.install.model.UpdateAvailability
|
||||
import com.google.firebase.crashlytics.ktx.crashlytics
|
||||
import com.google.firebase.ktx.Firebase
|
||||
import io.nekohasekai.libbox.Libbox
|
||||
import io.nekohasekai.libbox.ProfileContent
|
||||
import io.nekohasekai.sfa.Application
|
||||
import io.nekohasekai.sfa.BuildConfig
|
||||
import io.nekohasekai.sfa.R
|
||||
import io.nekohasekai.sfa.bg.ServiceConnection
|
||||
import io.nekohasekai.sfa.bg.ServiceNotification
|
||||
|
@ -45,17 +42,16 @@ import io.nekohasekai.sfa.ktx.errorDialogBuilder
|
|||
import io.nekohasekai.sfa.ui.profile.NewProfileActivity
|
||||
import io.nekohasekai.sfa.ui.shared.AbstractActivity
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
import java.util.Date
|
||||
import java.util.LinkedList
|
||||
|
||||
class MainActivity : AbstractActivity(), ServiceConnection.Callback, DistributeListener {
|
||||
class MainActivity : AbstractActivity(), ServiceConnection.Callback {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "MyActivity"
|
||||
private const val TAG = "MainActivity"
|
||||
}
|
||||
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
|
@ -86,7 +82,7 @@ class MainActivity : AbstractActivity(), ServiceConnection.Callback, DistributeL
|
|||
binding.navView.setupWithNavController(navController)
|
||||
|
||||
reconnect()
|
||||
startAnalysis()
|
||||
startIntegration()
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
|
@ -182,109 +178,76 @@ class MainActivity : AbstractActivity(), ServiceConnection.Callback, DistributeL
|
|||
connection.reconnect()
|
||||
}
|
||||
|
||||
private fun startAnalysis() {
|
||||
private fun startIntegration() {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
when (Settings.analyticsAllowed) {
|
||||
Settings.ANALYSIS_UNKNOWN -> {
|
||||
withContext(Dispatchers.Main) {
|
||||
showAnalysisDialog()
|
||||
}
|
||||
}
|
||||
|
||||
Settings.ANALYSIS_ALLOWED -> {
|
||||
startAnalysisInternal()
|
||||
if (Settings.errorReportingEnabled == Settings.ERROR_REPORTING_UNKNOWN) {
|
||||
withContext(Dispatchers.Main) {
|
||||
confirmErrorReportingIntegration()
|
||||
}
|
||||
} else if (Settings.checkUpdateEnabled) {
|
||||
checkUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showAnalysisDialog() {
|
||||
val builder = MaterialAlertDialogBuilder(this)
|
||||
.setTitle(getString(R.string.analytics_title))
|
||||
.setMessage(getString(R.string.analytics_message))
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
Settings.analyticsAllowed = Settings.ANALYSIS_ALLOWED
|
||||
startAnalysisInternal()
|
||||
private fun checkUpdate() {
|
||||
val appUpdateManager = AppUpdateManagerFactory.create(this)
|
||||
val appUpdateInfoTask = appUpdateManager.appUpdateInfo
|
||||
appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
|
||||
when (appUpdateInfo.updateAvailability()) {
|
||||
UpdateAvailability.UPDATE_NOT_AVAILABLE -> {
|
||||
Log.d(TAG, "checkUpdate: not available")
|
||||
}
|
||||
|
||||
UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS -> {
|
||||
when (appUpdateInfo.installStatus()) {
|
||||
InstallStatus.DOWNLOADED -> {
|
||||
appUpdateManager.completeUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateAvailability.UPDATE_AVAILABLE -> {
|
||||
if (appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
|
||||
appUpdateManager.startUpdateFlow(
|
||||
appUpdateInfo,
|
||||
this,
|
||||
AppUpdateOptions.newBuilder(AppUpdateType.FLEXIBLE).build()
|
||||
)
|
||||
} else if (appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) {
|
||||
appUpdateManager.startUpdateFlow(
|
||||
appUpdateInfo,
|
||||
this,
|
||||
AppUpdateOptions.newBuilder(AppUpdateType.IMMEDIATE).build()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
UpdateAvailability.UNKNOWN -> {
|
||||
}
|
||||
}
|
||||
.setNegativeButton(getString(R.string.no_thanks)) { _, _ ->
|
||||
}
|
||||
appUpdateInfoTask.addOnFailureListener {
|
||||
Log.e(TAG, "checkUpdate: ", it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun confirmErrorReportingIntegration() {
|
||||
val builder = MaterialAlertDialogBuilder(this).setTitle(getString(R.string.error_reporting))
|
||||
.setMessage(R.string.error_reporting_message)
|
||||
.setPositiveButton(getString(R.string.ok)) { _, _ ->
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
Settings.analyticsAllowed = Settings.ANALYSIS_DISALLOWED
|
||||
Settings.errorReportingEnabled = Settings.ERROR_REPORTING_ALLOWED
|
||||
Firebase.crashlytics.setCrashlyticsCollectionEnabled(true)
|
||||
}
|
||||
}.setNegativeButton(getString(R.string.no_thanks)) { _, _ ->
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
Settings.errorReportingEnabled = Settings.ERROR_REPORTING_DISALLOWED
|
||||
}
|
||||
}
|
||||
runCatching { builder.show() }
|
||||
}
|
||||
|
||||
suspend fun startAnalysisInternal() {
|
||||
if (BuildConfig.APPCENTER_SECRET.isBlank()) {
|
||||
return
|
||||
}
|
||||
Distribute.setListener(this)
|
||||
runCatching {
|
||||
AppCenter.start(
|
||||
application,
|
||||
BuildConfig.APPCENTER_SECRET,
|
||||
Analytics::class.java,
|
||||
Crashes::class.java,
|
||||
Distribute::class.java,
|
||||
)
|
||||
if (!Settings.checkUpdateEnabled) {
|
||||
Distribute.disableAutomaticCheckForUpdate()
|
||||
}
|
||||
}.onFailure {
|
||||
withContext(Dispatchers.Main) {
|
||||
errorDialogBuilder(it).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onReleaseAvailable(activity: Activity, releaseDetails: ReleaseDetails): Boolean {
|
||||
lifecycleScope.launch(Dispatchers.Main) {
|
||||
delay(2000L)
|
||||
runCatching {
|
||||
onReleaseAvailable0(releaseDetails)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun onReleaseAvailable0(releaseDetails: ReleaseDetails) {
|
||||
val builder = MaterialAlertDialogBuilder(this)
|
||||
.setTitle(getString(com.microsoft.appcenter.distribute.R.string.appcenter_distribute_update_dialog_title))
|
||||
var message = if (releaseDetails.isMandatoryUpdate) {
|
||||
getString(com.microsoft.appcenter.distribute.R.string.appcenter_distribute_update_dialog_message_mandatory)
|
||||
} else {
|
||||
getString(com.microsoft.appcenter.distribute.R.string.appcenter_distribute_update_dialog_message_optional)
|
||||
}
|
||||
message = String.format(
|
||||
message,
|
||||
AppNameHelper.getAppName(this),
|
||||
releaseDetails.shortVersion,
|
||||
releaseDetails.version
|
||||
)
|
||||
builder.setMessage(message)
|
||||
builder.setPositiveButton(com.microsoft.appcenter.distribute.R.string.appcenter_distribute_update_dialog_download) { _, _ ->
|
||||
startActivity(Intent(Intent.ACTION_VIEW, releaseDetails.downloadUrl))
|
||||
}
|
||||
builder.setCancelable(false)
|
||||
if (!releaseDetails.isMandatoryUpdate) {
|
||||
builder.setNegativeButton(com.microsoft.appcenter.distribute.R.string.appcenter_distribute_update_dialog_postpone) { _, _ ->
|
||||
Distribute.notifyUpdateAction(UpdateAction.POSTPONE)
|
||||
}
|
||||
}
|
||||
if (!TextUtils.isEmpty(releaseDetails.releaseNotes) && releaseDetails.releaseNotesUrl != null) {
|
||||
builder.setNeutralButton(com.microsoft.appcenter.distribute.R.string.appcenter_distribute_update_dialog_view_release_notes) { _, _ ->
|
||||
startActivity(Intent(Intent.ACTION_VIEW, releaseDetails.releaseNotesUrl))
|
||||
}
|
||||
}
|
||||
builder.show()
|
||||
}
|
||||
|
||||
override fun onNoReleaseAvailable(activity: Activity) {
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
fun startService() {
|
||||
if (!ServiceNotification.checkPermission()) {
|
||||
|
|
|
@ -11,8 +11,8 @@ import androidx.activity.result.contract.ActivityResultContracts
|
|||
import androidx.core.view.isGone
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.microsoft.appcenter.AppCenter
|
||||
import com.microsoft.appcenter.distribute.Distribute
|
||||
import com.google.firebase.crashlytics.ktx.crashlytics
|
||||
import com.google.firebase.ktx.Firebase
|
||||
import io.nekohasekai.libbox.Libbox
|
||||
import io.nekohasekai.sfa.Application
|
||||
import io.nekohasekai.sfa.R
|
||||
|
@ -60,31 +60,18 @@ class SettingsFragment : Fragment() {
|
|||
reloadSettings()
|
||||
}
|
||||
}
|
||||
binding.appCenterEnabled.addTextChangedListener {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val allowed = EnabledType.valueOf(it).boolValue
|
||||
Settings.analyticsAllowed =
|
||||
if (allowed) Settings.ANALYSIS_ALLOWED else Settings.ANALYSIS_DISALLOWED
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.checkUpdateEnabled.isEnabled = allowed
|
||||
}
|
||||
if (!allowed) {
|
||||
AppCenter.setEnabled(false)
|
||||
} else {
|
||||
if (!AppCenter.isConfigured()) {
|
||||
activity.startAnalysisInternal()
|
||||
}
|
||||
AppCenter.setEnabled(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.checkUpdateEnabled.addTextChangedListener {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val newValue = EnabledType.valueOf(it).boolValue
|
||||
Settings.checkUpdateEnabled = newValue
|
||||
if (!newValue) {
|
||||
Distribute.disableAutomaticCheckForUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.errorReportingEnabled.addTextChangedListener {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val newValue = EnabledType.valueOf(it).boolValue
|
||||
Settings.errorReportingEnabled =
|
||||
if (newValue) Settings.ERROR_REPORTING_ALLOWED else Settings.ERROR_REPORTING_DISALLOWED
|
||||
Firebase.crashlytics.setCrashlyticsCollectionEnabled(newValue)
|
||||
}
|
||||
}
|
||||
binding.disableMemoryLimit.addTextChangedListener {
|
||||
|
@ -128,23 +115,22 @@ class SettingsFragment : Fragment() {
|
|||
(activity.getExternalFilesDir(null) ?: activity.filesDir)
|
||||
.walkTopDown().filter { it.isFile }.map { it.length() }.sum()
|
||||
)
|
||||
val appCenterEnabled = Settings.analyticsAllowed == Settings.ANALYSIS_ALLOWED
|
||||
val errorReportingEnabled = Settings.errorReportingEnabled == Settings.ERROR_REPORTING_ALLOWED
|
||||
val checkUpdateEnabled = Settings.checkUpdateEnabled
|
||||
val removeBackgroudPermissionPage = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
val removeBackgroundPermissionPage = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
Application.powerManager.isIgnoringBatteryOptimizations(Application.application.packageName)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.dataSizeText.text = dataSize
|
||||
binding.appCenterEnabled.text = EnabledType.from(appCenterEnabled).name
|
||||
binding.appCenterEnabled.setSimpleItems(R.array.enabled)
|
||||
binding.checkUpdateEnabled.isEnabled = appCenterEnabled
|
||||
binding.errorReportingEnabled.text = EnabledType.from(errorReportingEnabled).name
|
||||
binding.errorReportingEnabled.setSimpleItems(R.array.enabled)
|
||||
binding.checkUpdateEnabled.text = EnabledType.from(checkUpdateEnabled).name
|
||||
binding.checkUpdateEnabled.setSimpleItems(R.array.enabled)
|
||||
binding.disableMemoryLimit.text = EnabledType.from(!Settings.disableMemoryLimit).name
|
||||
binding.disableMemoryLimit.setSimpleItems(R.array.enabled)
|
||||
binding.backgroundPermissionCard.isGone = removeBackgroudPermissionPage
|
||||
binding.backgroundPermissionCard.isGone = removeBackgroundPermissionPage
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -282,7 +282,7 @@ class PerAppProxyActivity : AbstractActivity() {
|
|||
|
||||
if (scanResult.isEmpty()) {
|
||||
MaterialAlertDialogBuilder(this@PerAppProxyActivity)
|
||||
.setTitle(R.string.message)
|
||||
.setTitle(R.string.title_scan_result)
|
||||
.setMessage(R.string.message_scan_app_no_apps_found)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show()
|
||||
|
|
1
app/src/main/play/release-notes/en-US/beta.txt
Normal file
1
app/src/main/play/release-notes/en-US/beta.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Fixes and improvements
|
|
@ -30,17 +30,17 @@
|
|||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/title_app_center"
|
||||
android:text="@string/title_app_settings"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:textAppearance="?attr/textAppearanceTitleLarge" />
|
||||
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/appCenterEnabled"
|
||||
android:id="@+id/checkUpdateEnabled"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:hint="@string/enabled">
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/check_update">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:layout_width="match_parent"
|
||||
|
@ -52,12 +52,12 @@
|
|||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/checkUpdateEnabled"
|
||||
android:id="@+id/errorReportingEnabled"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/check_update">
|
||||
android:hint="@string/error_reporting">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:layout_width="match_parent"
|
||||
|
@ -95,27 +95,11 @@
|
|||
|
||||
</TextView>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/disableMemoryLimit"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/memory_limit">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="none"
|
||||
android:text="@string/enabled"
|
||||
app:simpleItems="@array/enabled" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp">
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<TextView
|
||||
style="?attr/textAppearanceTitleSmall"
|
||||
|
@ -154,10 +138,27 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/disableMemoryLimit"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/memory_limit">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="none"
|
||||
android:text="@string/enabled"
|
||||
app:simpleItems="@array/enabled" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical|end"
|
||||
android:orientation="horizontal">
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
<string name="app_name">sing-box</string>
|
||||
|
||||
<string name="stop">Stop</string>
|
||||
<string name="ok">Ok</string>
|
||||
<string name="no_thanks">No, thanks</string>
|
||||
|
||||
<string name="title_dashboard">Dashboard</string>
|
||||
<string name="title_configuration">Profiles</string>
|
||||
|
@ -80,15 +82,10 @@
|
|||
<string name="core_version">Version</string>
|
||||
<string name="core">Core</string>
|
||||
<string name="core_data_size">Data Size</string>
|
||||
<string name="analytics_title">Analytics</string>
|
||||
<string name="analytics_message">Would you like to give SFA permission to collect analytics, send crash reports, and check update through AppCenter?</string>
|
||||
<string name="no_thanks">No, thanks</string>
|
||||
<string name="check_update">Check Update</string>
|
||||
<string name="title_app_center">App Center</string>
|
||||
<string name="title_feedback">Feedback</string>
|
||||
<string name="message">Message</string>
|
||||
<string name="send">Send</string>
|
||||
<string name="send_feedback">Send Feedback</string>
|
||||
<string name="error_reporting">Error Reporting</string>
|
||||
<string name="error_reporting_message">Would you like to allow sing to send error reports to developers via Firebase Crashlytics?</string>
|
||||
<string name="title_app_settings">App Settings</string>
|
||||
<string name="about_title">About</string>
|
||||
<string name="app_description">Android client for sing-box, the universal proxy platform.</string>
|
||||
<string name="documentation_button">Documentation</string>
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
buildscript {
|
||||
dependencies {
|
||||
classpath "gradle.plugin.com.betomorrow.gradle:appcenter-plugin:2.0.4"
|
||||
// https://github.com/invertase/react-native-firebase/issues/6983
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.2'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,5 +12,7 @@ plugins {
|
|||
id 'com.android.library' version '8.1.2' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.9.0' apply false
|
||||
id 'com.google.devtools.ksp' version '1.9.0-1.0.12' apply false
|
||||
id 'com.google.gms.google-services' version '4.4.0' apply false
|
||||
id 'com.github.triplet.play' version '3.8.4' apply false
|
||||
}
|
||||
|
||||
|
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,7 +1,7 @@
|
|||
#Sun Aug 20 19:43:30 CST 2023
|
||||
#Mon Oct 30 15:48:15 CST 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
networkTimeout=10000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue