22 Commits
2_2 ... 2_3

Author SHA1 Message Date
egor-white
91e627ced6 fix startActivity() crashes 2025-07-08 19:44:10 +03:00
CherretGit
0819cbab73 Update update.json 2025-07-08 21:47:24 +07:00
egor-white
dddac71bc6 Merge remote-tracking branch 'origin/main' 2025-07-08 17:31:18 +03:00
egor-white
2d4850c0e8 add Updater.kt mediastore if sdk < 30 2025-07-08 17:31:00 +03:00
CherretGit
a466ad8bcd Update update.json 2025-07-08 21:11:58 +07:00
CherretGit
1121365dfb Update changelog.md 2025-07-08 21:10:10 +07:00
egor-white
212df7fa9b Android 10 Storage crashes fix 2025-07-08 16:48:46 +03:00
egor-white
5e01ebae7d Merge pull request #3 from CherretGit/revert-1-main
Revert "Android 10 fix & update libs"
2025-07-08 14:57:44 +03:00
egor-white
2e2b33ca55 Revert "Android 10 fix & update libs" 2025-07-08 14:57:06 +03:00
egor-white
2d1a25bbc3 Merge pull request #1 from Likhach42/main
Android 10 fix
2025-07-08 14:47:39 +03:00
egor-white
4737e763ea Merge remote-tracking branch 'origin/main' into a10
# Conflicts:
#	app/build.gradle.kts
#	app/src/main/java/com/cherret/zaprett/MainActivity.kt
#	app/src/main/java/com/cherret/zaprett/ui/viewmodel/BaseListsViewModel.kt
#	app/src/main/java/com/cherret/zaprett/ui/viewmodel/HomeViewModel.kt
#	app/src/main/res/values-ru/strings.xml
#	app/src/main/res/values/strings.xml
#	gradle/libs.versions.toml
2025-07-08 14:39:23 +03:00
egor-white
8c93093b6b Update README.md 2025-07-08 09:44:43 +03:00
egor-white
0977d30729 Add files via upload 2025-07-08 09:43:43 +03:00
egor-white
f02b22d8bd Merge remote-tracking branch 'origin/main' 2025-07-07 14:14:59 +03:00
egor-white
6cf4a067fb fix status card text out of card 2025-07-07 14:14:37 +03:00
CherretGit
3fa009d3e9 Update update.json 2025-07-07 17:59:23 +07:00
CherretGit
0222ee5cfc Update update.json 2025-07-07 17:53:13 +07:00
CherretGit
e8c8a2a6c1 Update Updater.kt 2025-07-07 17:41:27 +07:00
egor-white
7c75174e26 fix installApk crashes 2025-07-07 13:40:00 +03:00
egor-white
c687d912b3 Update update.json 2025-07-07 12:47:07 +03:00
egor-white
6b017d116f Update changelog.md 2025-07-07 12:46:36 +03:00
maksim
c153b582e7 Android 10 fix & update libs 2025-06-27 20:19:48 +03:00
19 changed files with 115 additions and 41 deletions

View File

@@ -4,10 +4,10 @@
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2025-06-22T07:39:53.690794081Z">
<DropdownSelection timestamp="2025-07-08T13:21:50.180843436Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="Default" identifier="serial=10.0.0.189:40463;connection=ffec9c3f" />
<DeviceId pluginId="LocalEmulator" identifier="path=/home/white/.android/avd/Medium_Phone.avd" />
</handle>
</Target>
</DropdownSelection>

View File

@@ -16,3 +16,4 @@
## Скриншоты:
<img src="images/1.png" width="300"><img src="images/2.png" width="300"><img src="images/3.png" width="300"><img src="images/4.png" width="300"><img src="images/5.png" width="300">
<img src="images/6.png" width="300">
<img src="images/7.png" width="300">

View File

@@ -13,10 +13,10 @@ android {
defaultConfig {
applicationId = "com.cherret.zaprett"
minSdk = 30
minSdk = 29
targetSdk = 35
versionCode = 14
versionName = "2.2"
versionCode = 15
versionName = "2.3"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
ndk {

View File

@@ -14,6 +14,7 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<application
android:requestLegacyExternalStorage="true"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"

View File

@@ -1,6 +1,5 @@
package com.cherret.zaprett
import android.Manifest
import android.content.Context
import android.content.Intent
@@ -99,7 +98,18 @@ class MainActivity : ComponentActivity() {
}
}
}
var showStoragePermissionDialog by remember { mutableStateOf(!Environment.isExternalStorageManager()) }
var showStoragePermissionDialog by remember {
mutableStateOf(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
!Environment.isExternalStorageManager()
} else {
ContextCompat.checkSelfPermission(
this,
Manifest.permission.WRITE_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
}
)
}
var showNotificationPermissionDialog by remember {
mutableStateOf(
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
@@ -114,10 +124,20 @@ class MainActivity : ComponentActivity() {
title = stringResource(R.string.error_no_storage_title),
message = stringResource(R.string.error_no_storage_message),
onConfirm = {
val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
val uri = Uri.fromParts("package", packageName, null)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val intent = Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
val uri = Uri.fromParts("package", applicationContext.packageName, null)
intent.data = uri
startActivity(intent)
} else {
requestPermissions(
arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
),
100
)
}
showStoragePermissionDialog = false
},
onDismiss = { showStoragePermissionDialog = false }

View File

@@ -20,6 +20,7 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
@@ -61,6 +62,7 @@ import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
@@ -148,7 +150,8 @@ private fun ServiceStatusCard(viewModel: HomeViewModel, cardText: MutableState<I
modifier = Modifier
.fillMaxWidth()
.padding(start = 10.dp, top = 25.dp, end = 10.dp)
.height(150.dp),
//.height(150.dp)
.wrapContentHeight(),
onClick = { viewModel.onCardClick() }
) {
Row (
@@ -169,6 +172,9 @@ private fun ServiceStatusCard(viewModel: HomeViewModel, cardText: MutableState<I
Text(
text = stringResource(cardText.value),
fontFamily = FontFamily(Font(R.font.unbounded, FontWeight.Normal)),
fontSize = 16.sp,
//maxLines = 3,
//overflow = TextOverflow.Ellipsis,
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),

View File

@@ -2,7 +2,9 @@ package com.cherret.zaprett.ui.viewmodel
import android.app.Application
import android.content.Context
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.OpenableColumns
import androidx.compose.material3.SnackbarHostState
@@ -11,6 +13,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.core.content.ContextCompat
import androidx.lifecycle.AndroidViewModel
import com.cherret.zaprett.R
import com.cherret.zaprett.utils.getZaprettPath
@@ -20,6 +23,7 @@ import kotlinx.coroutines.launch
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.util.jar.Manifest
abstract class BaseListsViewModel(application: Application) : AndroidViewModel(application) {
val context = application
@@ -61,7 +65,11 @@ abstract class BaseListsViewModel(application: Application) : AndroidViewModel(a
}
fun copySelectedFile(context: Context, path: String, uri: Uri) {
//if (!Environment.isExternalStorageManager()) return
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
if (!Environment.isExternalStorageManager()) return
}
else if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) return
val contentResolver = context.contentResolver
val fileName = contentResolver.query(uri, null, null, null, null)?.use { cursor ->
val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
@@ -72,9 +80,29 @@ abstract class BaseListsViewModel(application: Application) : AndroidViewModel(a
if (!directory.exists()) {
directory.mkdirs()
}
val outputFile = File(getZaprettPath() + path, fileName)
try {
val outputFile = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (Environment.isExternalStorageManager()) {
val outputDir = File(getZaprettPath() + path)
if (!outputDir.exists()) {
outputDir.mkdirs()
}
File(outputDir, fileName)
} else {
val outputDir = File(context.filesDir, path)
if (!outputDir.exists()) {
outputDir.mkdirs()
}
File(outputDir, fileName)
}
} else {
val outputDir = File(context.filesDir, path)
if (!outputDir.exists()) {
outputDir.mkdirs()
}
File(outputDir, fileName)
}
contentResolver.openInputStream(uri)?.use { inputStream ->
FileOutputStream(outputFile).use { outputStream ->
inputStream.copyTo(outputStream)

View File

@@ -3,6 +3,10 @@ package com.cherret.zaprett.ui.viewmodel
import android.app.Application
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Debug
import android.provider.Settings
import android.util.Log
import android.widget.Toast
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Help
@@ -87,22 +91,22 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
if (prefs.getBoolean("use_module", false) && prefs.getBoolean("update_on_boot", false)) {
getStatus { isEnabled ->
if (isEnabled){
cardText.value = R.string.status_enabled
cardText.intValue = R.string.status_enabled
cardIcon.value = Icons.Filled.CheckCircle
}
else {
cardText.value = R.string.status_disabled
cardText.intValue = R.string.status_disabled
cardIcon.value = Icons.Filled.Cancel
}
}
}
else {
if (ByeDpiVpnService.status == ServiceStatus.Connected){
cardText.value = R.string.status_enabled
cardText.intValue = R.string.status_enabled
cardIcon.value = Icons.Filled.CheckCircle
}
else {
cardText.value = R.string.status_disabled
cardText.intValue = R.string.status_disabled
cardIcon.value = Icons.Filled.Cancel
}
}
@@ -112,7 +116,7 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
if (prefs.getBoolean("use_module", false)) {
getStatus { isEnabled ->
if (isEnabled){
cardText.value = R.string.status_enabled
cardText.intValue = R.string.status_enabled
cardIcon.value = Icons.Filled.CheckCircle
}
else {
@@ -242,11 +246,19 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
fun onUpdateConfirm() {
showUpdateDialog.value = false
if (context.packageManager.canRequestPackageInstalls()){
val id = download(context, downloadUrl.value.orEmpty())
registerDownloadListener(context, id) { uri ->
installApk(context, uri)
}
}
else {
val packageUri = Uri.fromParts("package", context.packageName, null)
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageUri).addFlags(
Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
}
}
fun parseArgs(ip: String, port: String, lines: List<String>): Array<String> {
val regex = Regex("""--?\S+(?:=(?:[^"'\s]+|"[^"]*"|'[^']*'))?|[^\s]+""")

View File

@@ -3,13 +3,16 @@ package com.cherret.zaprett.utils
import android.annotation.SuppressLint
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import android.provider.Settings
import android.util.Log
import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider
import androidx.core.net.toUri
@@ -78,7 +81,22 @@ fun download(context: Context, url: String): Long {
setTitle(fileName)
setDescription(fileName)
setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
val contentValues = ContentValues().apply {
put(MediaStore.Downloads.DISPLAY_NAME, fileName)
put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS)
}
val uri = context.contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)
if (uri != null) {
setDestinationUri(uri)
} else {
Log.e("Updater", "Failed to create MediaStore URI")
return -1L
}
} else {
setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)
}
setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
}
return downloadManager.enqueue(request)
@@ -94,19 +112,9 @@ fun installApk(context: Context, uri: Uri) {
}
context.startActivity(intent)
}
else {
val packageUri = Uri.fromParts("package", context.packageName, null)
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageUri)
context.startActivity(intent)
}
}
fun registerDownloadListener(context: Context, downloadId: Long, onDownloaded: (Uri) -> Unit) {// AI Generated
if (!context.packageManager.canRequestPackageInstalls()){
val packageUri = Uri.fromParts("package", context.packageName, null)
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageUri)
context.startActivity(intent)
}
val receiver = object : BroadcastReceiver() {
@SuppressLint("Range")
override fun onReceive(context: Context?, intent: Intent?) {

View File

@@ -1,3 +1 @@
Исправление багов в фрагменте хостов
Исправление сплющивания карточки информации о модуле
Перенос версии byedpi в соответствующее место
Поддержка Android 10(спасибо @Likhach42)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 113 KiB

BIN
images/7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

View File

@@ -1,6 +1,6 @@
{
"version": "2.1",
"versionCode": 13,
"downloadUrl": "https://github.com/CherretGit/zaprett-app/releases/download/2_1/app-release.apk",
"version": "2.3",
"versionCode": 15,
"downloadUrl": "https://github.com/CherretGit/zaprett-app/releases/download/2_3/app-release.apk",
"changelogUrl": "https://raw.githubusercontent.com/CherretGit/zaprett-app/refs/heads/main/changelog.md"
}