mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-07-23 09:29:41 +02:00
Probably fixed
This commit is contained in:
@@ -105,8 +105,6 @@ dependencies {
|
|||||||
implementation "dev.rikka.hidden:compat:$hidden_api_version"
|
implementation "dev.rikka.hidden:compat:$hidden_api_version"
|
||||||
compileOnly "dev.rikka.hidden:stub:$hidden_api_version"
|
compileOnly "dev.rikka.hidden:stub:$hidden_api_version"
|
||||||
implementation "org.lsposed.hiddenapibypass:hiddenapibypass:4.3"
|
implementation "org.lsposed.hiddenapibypass:hiddenapibypass:4.3"
|
||||||
|
|
||||||
implementation "com.github.topjohnwu.libsu:core:5.2.2"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ext.abiCodes = ["x86_64": 1, "armeabi-v7a": 2, "arm64-v8a": 3]
|
ext.abiCodes = ["x86_64": 1, "armeabi-v7a": 2, "arm64-v8a": 3]
|
||||||
|
@@ -11,7 +11,6 @@ import android.os.Build
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Process
|
import android.os.Process
|
||||||
import androidx.annotation.NonNull
|
import androidx.annotation.NonNull
|
||||||
import com.topjohnwu.superuser.Shell
|
|
||||||
import dev.imranr.obtainium.util.IIntentSenderAdaptor
|
import dev.imranr.obtainium.util.IIntentSenderAdaptor
|
||||||
import dev.imranr.obtainium.util.IntentSenderUtils
|
import dev.imranr.obtainium.util.IntentSenderUtils
|
||||||
import dev.imranr.obtainium.util.PackageInstallerUtils
|
import dev.imranr.obtainium.util.PackageInstallerUtils
|
||||||
@@ -23,13 +22,15 @@ import io.flutter.plugin.common.MethodChannel.Result
|
|||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
import org.lsposed.hiddenapibypass.HiddenApiBypass
|
import org.lsposed.hiddenapibypass.HiddenApiBypass
|
||||||
|
import kotlinx.coroutines.async
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
import rikka.shizuku.Shizuku
|
import rikka.shizuku.Shizuku
|
||||||
import rikka.shizuku.Shizuku.OnRequestPermissionResultListener
|
import rikka.shizuku.Shizuku.OnRequestPermissionResultListener
|
||||||
import rikka.shizuku.ShizukuBinderWrapper
|
import rikka.shizuku.ShizukuBinderWrapper
|
||||||
|
|
||||||
class MainActivity: FlutterActivity() {
|
class MainActivity: FlutterActivity() {
|
||||||
private var nativeChannel: MethodChannel? = null
|
private var nativeChannel: MethodChannel? = null
|
||||||
private val SHIZUKU_PERMISSION_REQUEST_CODE = (10..200).random()
|
private val SHIZUKU_PERMISSION_REQUEST_CODE = 1492
|
||||||
|
|
||||||
private fun shizukuCheckPermission(result: Result) {
|
private fun shizukuCheckPermission(result: Result) {
|
||||||
try {
|
try {
|
||||||
@@ -43,7 +44,7 @@ class MainActivity: FlutterActivity() {
|
|||||||
Shizuku.requestPermission(SHIZUKU_PERMISSION_REQUEST_CODE)
|
Shizuku.requestPermission(SHIZUKU_PERMISSION_REQUEST_CODE)
|
||||||
result.success(-2)
|
result.success(-2)
|
||||||
}
|
}
|
||||||
} catch (_: Exception) { // If shizuku not running
|
} catch (_: Exception) { // If shizuku binder not found
|
||||||
result.success(-1)
|
result.success(-1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -56,7 +57,7 @@ class MainActivity: FlutterActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun shizukuInstallApk(apkFileUri: String, result: Result) {
|
private suspend fun shizukuInstallApk(apkFileUri: String, result: Result) {
|
||||||
val uri = Uri.parse(apkFileUri)
|
val uri = Uri.parse(apkFileUri)
|
||||||
var res = false
|
var res = false
|
||||||
var session: PackageInstaller.Session? = null
|
var session: PackageInstaller.Session? = null
|
||||||
@@ -129,22 +130,6 @@ class MainActivity: FlutterActivity() {
|
|||||||
result.success(res)
|
result.success(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun rootCheckPermission(result: Result) {
|
|
||||||
Shell.getShell(Shell.GetShellCallback(
|
|
||||||
fun(shell: Shell) {
|
|
||||||
result.success(shell.isRoot)
|
|
||||||
}
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun rootInstallApk(apkFilePath: String, result: Result) {
|
|
||||||
Shell.sh("pm install -r -t " + apkFilePath).submit { out ->
|
|
||||||
val builder = StringBuilder()
|
|
||||||
for (data in out.getOut()) { builder.append(data) }
|
|
||||||
result.success(builder.toString().endsWith("Success"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
|
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
|
||||||
super.configureFlutterEngine(flutterEngine)
|
super.configureFlutterEngine(flutterEngine)
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
@@ -160,14 +145,9 @@ class MainActivity: FlutterActivity() {
|
|||||||
result.success(res)
|
result.success(res)
|
||||||
} else if (call.method == "checkPermissionShizuku") {
|
} else if (call.method == "checkPermissionShizuku") {
|
||||||
shizukuCheckPermission(result)
|
shizukuCheckPermission(result)
|
||||||
} else if (call.method == "checkPermissionRoot") {
|
|
||||||
rootCheckPermission(result)
|
|
||||||
} else if (call.method == "installWithShizuku") {
|
} else if (call.method == "installWithShizuku") {
|
||||||
val apkFileUri: String? = call.argument("apkFileUri")
|
val apkFileUri: String = call.argument("apkFileUri")!!
|
||||||
shizukuInstallApk(apkFileUri!!, result)
|
GlobalScope.async { shizukuInstallApk(apkFileUri, result) }
|
||||||
} else if (call.method == "installWithRoot") {
|
|
||||||
val apkFilePath: String? = call.argument("apkFilePath")
|
|
||||||
rootInstallApk(apkFilePath!!, result)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -280,9 +280,7 @@
|
|||||||
"supportFixedAPKURL": "Support fixed APK URLs",
|
"supportFixedAPKURL": "Support fixed APK URLs",
|
||||||
"selectX": "Select {}",
|
"selectX": "Select {}",
|
||||||
"parallelDownloads": "Allow parallel downloads",
|
"parallelDownloads": "Allow parallel downloads",
|
||||||
"installMethod": "Installation method",
|
"useShizuku": "Use Shizuku or Sui to install",
|
||||||
"normal": "Normal",
|
|
||||||
"root": "Root",
|
|
||||||
"shizukuBinderNotFound": "Сompatible Shizuku service wasn't found",
|
"shizukuBinderNotFound": "Сompatible Shizuku service wasn't found",
|
||||||
"useSystemFont": "Use the system font",
|
"useSystemFont": "Use the system font",
|
||||||
"systemFontError": "Error loading the system font: {}",
|
"systemFontError": "Error loading the system font: {}",
|
||||||
|
@@ -281,9 +281,7 @@
|
|||||||
"supportFixedAPKURL": "Поддержка фиксированных URL-адресов APK",
|
"supportFixedAPKURL": "Поддержка фиксированных URL-адресов APK",
|
||||||
"selectX": "Выбрать {}",
|
"selectX": "Выбрать {}",
|
||||||
"parallelDownloads": "Разрешить параллельные загрузки",
|
"parallelDownloads": "Разрешить параллельные загрузки",
|
||||||
"installMethod": "Метод установки",
|
"useShizuku": "Использовать Shizuku или Sui для установки",
|
||||||
"normal": "Нормальный",
|
|
||||||
"root": "Суперпользователь",
|
|
||||||
"shizukuBinderNotFound": "Совместимый сервис Shizuku не найден",
|
"shizukuBinderNotFound": "Совместимый сервис Shizuku не найден",
|
||||||
"useSystemFont": "Использовать системный шрифт",
|
"useSystemFont": "Использовать системный шрифт",
|
||||||
"systemFontError": "Ошибка загрузки системного шрифта: {}",
|
"systemFontError": "Ошибка загрузки системного шрифта: {}",
|
||||||
|
@@ -30,29 +30,6 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
settingsProvider.initializeSettings();
|
settingsProvider.initializeSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
var installMethodDropdown = DropdownButtonFormField(
|
|
||||||
decoration: InputDecoration(labelText: tr('installMethod')),
|
|
||||||
value: settingsProvider.installMethod,
|
|
||||||
items: [
|
|
||||||
DropdownMenuItem(
|
|
||||||
value: InstallMethodSettings.normal,
|
|
||||||
child: Text(tr('normal')),
|
|
||||||
),
|
|
||||||
const DropdownMenuItem(
|
|
||||||
value: InstallMethodSettings.shizuku,
|
|
||||||
child: Text('Shizuku'),
|
|
||||||
),
|
|
||||||
DropdownMenuItem(
|
|
||||||
value: InstallMethodSettings.root,
|
|
||||||
child: Text(tr('root')),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
onChanged: (value) {
|
|
||||||
if (value != null) {
|
|
||||||
settingsProvider.installMethod = value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var themeDropdown = DropdownButtonFormField(
|
var themeDropdown = DropdownButtonFormField(
|
||||||
decoration: InputDecoration(labelText: tr('theme')),
|
decoration: InputDecoration(labelText: tr('theme')),
|
||||||
value: settingsProvider.theme,
|
value: settingsProvider.theme,
|
||||||
@@ -363,7 +340,29 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
})
|
})
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
installMethodDropdown,
|
height16,
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Flexible(child: Text(tr('useShizuku'))),
|
||||||
|
Switch(
|
||||||
|
value: settingsProvider.useShizuku,
|
||||||
|
onChanged: (useShizuku) {
|
||||||
|
if (useShizuku) {
|
||||||
|
NativeFeatures.checkPermissionShizuku().then((resCode) {
|
||||||
|
settingsProvider.useShizuku = resCode == 1;
|
||||||
|
if (resCode == 0) {
|
||||||
|
showError(ObtainiumError(tr('cancelled')), context);
|
||||||
|
} else if (resCode == -1) {
|
||||||
|
showError(ObtainiumError(tr('shizukuBinderNotFound')), context);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
settingsProvider.useShizuku = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
),
|
||||||
height32,
|
height32,
|
||||||
Text(
|
Text(
|
||||||
tr('sourceSpecific'),
|
tr('sourceSpecific'),
|
||||||
|
@@ -547,8 +547,7 @@ class AppsProvider with ChangeNotifier {
|
|||||||
!(await canDowngradeApps())) {
|
!(await canDowngradeApps())) {
|
||||||
throw DowngradeError();
|
throw DowngradeError();
|
||||||
}
|
}
|
||||||
if (needsBGWorkaround &&
|
if (needsBGWorkaround) {
|
||||||
settingsProvider.installMethod == InstallMethodSettings.normal) {
|
|
||||||
// The below 'await' will never return if we are in a background process
|
// The below 'await' will never return if we are in a background process
|
||||||
// To work around this, we should assume the install will be successful
|
// To work around this, we should assume the install will be successful
|
||||||
// So we update the app's installed version first as we will never get to the later code
|
// So we update the app's installed version first as we will never get to the later code
|
||||||
@@ -560,20 +559,14 @@ class AppsProvider with ChangeNotifier {
|
|||||||
attemptToCorrectInstallStatus: false);
|
attemptToCorrectInstallStatus: false);
|
||||||
}
|
}
|
||||||
int? code;
|
int? code;
|
||||||
switch (settingsProvider.installMethod) {
|
if (!settingsProvider.useShizuku) {
|
||||||
case InstallMethodSettings.normal:
|
code = await AndroidPackageInstaller.installApk(
|
||||||
code = await AndroidPackageInstaller.installApk(
|
apkFilePath: file.file.path);
|
||||||
apkFilePath: file.file.path);
|
} else {
|
||||||
case InstallMethodSettings.shizuku:
|
code = (await NativeFeatures.installWithShizuku(
|
||||||
code = (await NativeFeatures.installWithShizuku(
|
apkFileUri: file.file.uri.toString()))
|
||||||
apkFileUri: file.file.uri.toString()))
|
? 0
|
||||||
? 0
|
: 1;
|
||||||
: 1;
|
|
||||||
case InstallMethodSettings.root:
|
|
||||||
code =
|
|
||||||
(await NativeFeatures.installWithRoot(apkFilePath: file.file.path))
|
|
||||||
? 0
|
|
||||||
: 1;
|
|
||||||
}
|
}
|
||||||
bool installed = false;
|
bool installed = false;
|
||||||
if (code != null && code != 0 && code != 3) {
|
if (code != null && code != 0 && code != 3) {
|
||||||
@@ -732,25 +725,19 @@ class AppsProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
var appId = downloadedFile?.appId ?? downloadedDir!.appId;
|
var appId = downloadedFile?.appId ?? downloadedDir!.appId;
|
||||||
bool willBeSilent = await canInstallSilently(apps[appId]!.app);
|
bool willBeSilent = await canInstallSilently(apps[appId]!.app);
|
||||||
switch (settingsProvider.installMethod) {
|
if (!settingsProvider.useShizuku) {
|
||||||
case InstallMethodSettings.normal:
|
if (!(await settingsProvider.getInstallPermission(enforce: false))) {
|
||||||
if (!(await settingsProvider.getInstallPermission(
|
throw ObtainiumError(tr('cancelled'));
|
||||||
enforce: false))) {
|
}
|
||||||
throw ObtainiumError(tr('cancelled'));
|
} else {
|
||||||
}
|
int code = await NativeFeatures.checkPermissionShizuku();
|
||||||
case InstallMethodSettings.shizuku:
|
if (code == 0) {
|
||||||
int code = await NativeFeatures.checkPermissionShizuku();
|
throw ObtainiumError(tr('cancelled'));
|
||||||
if (code == -1) {
|
} else if (code == -1) {
|
||||||
throw ObtainiumError(tr('shizukuBinderNotFound'));
|
throw ObtainiumError(tr('shizukuBinderNotFound'));
|
||||||
} else if (code == 0) {
|
}
|
||||||
throw ObtainiumError(tr('cancelled'));
|
|
||||||
}
|
|
||||||
case InstallMethodSettings.root:
|
|
||||||
if (!(await NativeFeatures.checkPermissionRoot())) {
|
|
||||||
throw ObtainiumError(tr('cancelled'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!willBeSilent && context != null) {
|
if (!willBeSilent && context != null && !settingsProvider.useShizuku) {
|
||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
await waitForUserToReturnToForeground(context);
|
await waitForUserToReturnToForeground(context);
|
||||||
}
|
}
|
||||||
|
@@ -59,17 +59,8 @@ class NativeFeatures {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<bool> checkPermissionRoot() async {
|
|
||||||
return await _channel.invokeMethod('checkPermissionRoot');
|
|
||||||
}
|
|
||||||
|
|
||||||
static Future<bool> installWithShizuku({required String apkFileUri}) async {
|
static Future<bool> installWithShizuku({required String apkFileUri}) async {
|
||||||
return await _channel.invokeMethod(
|
return await _channel.invokeMethod(
|
||||||
'installWithShizuku', {'apkFileUri': apkFileUri});
|
'installWithShizuku', {'apkFileUri': apkFileUri});
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<bool> installWithRoot({required String apkFilePath}) async {
|
|
||||||
return await _channel.invokeMethod(
|
|
||||||
'installWithRoot', {'apkFilePath': apkFilePath});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -18,8 +18,6 @@ String obtainiumTempId = 'imranr98_obtainium_${GitHub().hosts[0]}';
|
|||||||
String obtainiumId = 'dev.imranr.obtainium';
|
String obtainiumId = 'dev.imranr.obtainium';
|
||||||
String obtainiumUrl = 'https://github.com/ImranR98/Obtainium';
|
String obtainiumUrl = 'https://github.com/ImranR98/Obtainium';
|
||||||
|
|
||||||
enum InstallMethodSettings { normal, shizuku, root }
|
|
||||||
|
|
||||||
enum ThemeSettings { system, light, dark }
|
enum ThemeSettings { system, light, dark }
|
||||||
|
|
||||||
enum ColourSettings { basic, materialYou }
|
enum ColourSettings { basic, materialYou }
|
||||||
@@ -61,13 +59,12 @@ class SettingsProvider with ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
InstallMethodSettings get installMethod {
|
bool get useShizuku{
|
||||||
return InstallMethodSettings.values[
|
return prefs?.getBool('useShizuku') ?? false;
|
||||||
prefs?.getInt('installMethod') ?? InstallMethodSettings.normal.index];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set installMethod(InstallMethodSettings t) {
|
set useShizuku(bool useShizuku) {
|
||||||
prefs?.setInt('installMethod', t.index);
|
prefs?.setBool('useShizuku', useShizuku);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user