mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-07-17 15:16:43 +02:00
System font and newer dependencies
This commit is contained in:
@ -37,12 +37,12 @@ android {
|
|||||||
ndkVersion flutter.ndkVersion
|
ndkVersion flutter.ndkVersion
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_17
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_17
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = '1.8'
|
jvmTarget = '17'
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
@ -96,16 +96,11 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
|
||||||
|
|
||||||
def shizuku_version = '13.1.5'
|
def shizuku_version = '13.1.5'
|
||||||
implementation "dev.rikka.shizuku:api:$shizuku_version"
|
implementation "dev.rikka.shizuku:api:$shizuku_version"
|
||||||
implementation "dev.rikka.shizuku:provider:$shizuku_version"
|
implementation "dev.rikka.shizuku:provider:$shizuku_version"
|
||||||
|
|
||||||
def hidden_api_version = '4.1.0'
|
def hidden_api_version = '4.3.1'
|
||||||
// DO NOT UPDATE Hidden API without updating the Android tools
|
|
||||||
// and do not update Android tools without updating the whole Flutter
|
|
||||||
// (also in android/build.gradle)
|
|
||||||
implementation "dev.rikka.tools.refine:runtime:$hidden_api_version"
|
implementation "dev.rikka.tools.refine:runtime:$hidden_api_version"
|
||||||
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"
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
package dev.imranr.obtainium
|
||||||
|
|
||||||
|
import android.util.Xml
|
||||||
|
import org.xmlpull.v1.XmlPullParser
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
|
|
||||||
|
class DefaultSystemFont {
|
||||||
|
fun get(): String? {
|
||||||
|
return try {
|
||||||
|
val file = File("/system/etc/fonts.xml")
|
||||||
|
val fileStream = FileInputStream(file)
|
||||||
|
parseFontsFileStream(fileStream)
|
||||||
|
} catch (_: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseFontsFileStream(fileStream: FileInputStream): String {
|
||||||
|
fileStream.use { stream ->
|
||||||
|
val parser = Xml.newPullParser()
|
||||||
|
parser.setInput(stream, null)
|
||||||
|
parser.nextTag()
|
||||||
|
return parseFonts(parser)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseFonts(parser: XmlPullParser): String {
|
||||||
|
while (parser.name != "font") { parser.next() }
|
||||||
|
parser.next()
|
||||||
|
return "/system/fonts/" + parser.text.trim()
|
||||||
|
}
|
||||||
|
}
|
@ -28,7 +28,7 @@ import rikka.shizuku.Shizuku.OnRequestPermissionResultListener
|
|||||||
import rikka.shizuku.ShizukuBinderWrapper
|
import rikka.shizuku.ShizukuBinderWrapper
|
||||||
|
|
||||||
class MainActivity: FlutterActivity() {
|
class MainActivity: FlutterActivity() {
|
||||||
private var installersChannel: MethodChannel? = null
|
private var nativeChannel: MethodChannel? = null
|
||||||
private val SHIZUKU_PERMISSION_REQUEST_CODE = (10..200).random()
|
private val SHIZUKU_PERMISSION_REQUEST_CODE = (10..200).random()
|
||||||
|
|
||||||
private fun shizukuCheckPermission(result: Result) {
|
private fun shizukuCheckPermission(result: Result) {
|
||||||
@ -52,7 +52,7 @@ class MainActivity: FlutterActivity() {
|
|||||||
requestCode: Int, grantResult: Int ->
|
requestCode: Int, grantResult: Int ->
|
||||||
if (requestCode == SHIZUKU_PERMISSION_REQUEST_CODE) {
|
if (requestCode == SHIZUKU_PERMISSION_REQUEST_CODE) {
|
||||||
val res = if (grantResult == PackageManager.PERMISSION_GRANTED) 1 else 0
|
val res = if (grantResult == PackageManager.PERMISSION_GRANTED) 1 else 0
|
||||||
installersChannel!!.invokeMethod("resPermShizuku", mapOf("res" to res))
|
nativeChannel!!.invokeMethod("resPermShizuku", mapOf("res" to res))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,11 +151,14 @@ class MainActivity: FlutterActivity() {
|
|||||||
HiddenApiBypass.addHiddenApiExemptions("")
|
HiddenApiBypass.addHiddenApiExemptions("")
|
||||||
}
|
}
|
||||||
Shizuku.addRequestPermissionResultListener(shizukuRequestPermissionResultListener)
|
Shizuku.addRequestPermissionResultListener(shizukuRequestPermissionResultListener)
|
||||||
installersChannel = MethodChannel(
|
nativeChannel = MethodChannel(
|
||||||
flutterEngine.dartExecutor.binaryMessenger, "installers")
|
flutterEngine.dartExecutor.binaryMessenger, "native")
|
||||||
installersChannel!!.setMethodCallHandler {
|
nativeChannel!!.setMethodCallHandler {
|
||||||
call, result ->
|
call, result ->
|
||||||
if (call.method == "checkPermissionShizuku") {
|
if (call.method == "getSystemFont") {
|
||||||
|
val res = DefaultSystemFont().get()
|
||||||
|
result.success(res)
|
||||||
|
} else if (call.method == "checkPermissionShizuku") {
|
||||||
shizukuCheckPermission(result)
|
shizukuCheckPermission(result)
|
||||||
} else if (call.method == "checkPermissionRoot") {
|
} else if (call.method == "checkPermissionRoot") {
|
||||||
rootCheckPermission(result)
|
rootCheckPermission(result)
|
||||||
|
@ -6,9 +6,9 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.2.0'
|
classpath "com.android.tools.build:gradle:7.4.2"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath 'dev.rikka.tools.refine:gradle-plugin:4.1.0' // Do not update!
|
classpath "dev.rikka.tools.refine:gradle-plugin:4.3.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,7 +285,8 @@
|
|||||||
"normal": "Normal",
|
"normal": "Normal",
|
||||||
"shizuku": "Shizuku",
|
"shizuku": "Shizuku",
|
||||||
"root": "Root",
|
"root": "Root",
|
||||||
"shizukuBinderNotFound": "Shizuku is not running",
|
"shizukuBinderNotFound": "Сompatible Shizuku service wasn't found",
|
||||||
|
"tryUseSystemFont": "Try to use a system font",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Remove App?",
|
"one": "Remove App?",
|
||||||
"other": "Remove Apps?"
|
"other": "Remove Apps?"
|
||||||
|
@ -285,7 +285,8 @@
|
|||||||
"normal": "Нормальный",
|
"normal": "Нормальный",
|
||||||
"shizuku": "Shizuku",
|
"shizuku": "Shizuku",
|
||||||
"root": "Суперпользователь",
|
"root": "Суперпользователь",
|
||||||
"shizukuBinderNotFound": "Shizuku не запущен",
|
"shizukuBinderNotFound": "Совместимый сервис Shizuku не найден",
|
||||||
|
"tryUseSystemFont": "Попытаться использовать системный шрифт",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Удалить приложение?",
|
"one": "Удалить приложение?",
|
||||||
"other": "Удалить приложения?"
|
"other": "Удалить приложения?"
|
||||||
|
@ -5,6 +5,7 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:obtainium/pages/home.dart';
|
import 'package:obtainium/pages/home.dart';
|
||||||
import 'package:obtainium/providers/apps_provider.dart';
|
import 'package:obtainium/providers/apps_provider.dart';
|
||||||
import 'package:obtainium/providers/logs_provider.dart';
|
import 'package:obtainium/providers/logs_provider.dart';
|
||||||
|
import 'package:obtainium/providers/native_provider.dart';
|
||||||
import 'package:obtainium/providers/notifications_provider.dart';
|
import 'package:obtainium/providers/notifications_provider.dart';
|
||||||
import 'package:obtainium/providers/settings_provider.dart';
|
import 'package:obtainium/providers/settings_provider.dart';
|
||||||
import 'package:obtainium/providers/source_provider.dart';
|
import 'package:obtainium/providers/source_provider.dart';
|
||||||
@ -185,6 +186,16 @@ class _ObtainiumState extends State<Obtainium> {
|
|||||||
}
|
}
|
||||||
existingUpdateInterval = actualUpdateInterval;
|
existingUpdateInterval = actualUpdateInterval;
|
||||||
}
|
}
|
||||||
|
settingsProvider.addListener(() async {
|
||||||
|
if (settingsProvider.tryUseSystemFont &&
|
||||||
|
settingsProvider.appFont == "Metropolis") {
|
||||||
|
bool fontLoaded = await NativeFeatures.tryLoadSystemFont();
|
||||||
|
if (fontLoaded) { settingsProvider.appFont = "SystemFont"; }
|
||||||
|
} else if (!settingsProvider.tryUseSystemFont &&
|
||||||
|
settingsProvider.appFont != "Metropolis") {
|
||||||
|
settingsProvider.appFont = "Metropolis";
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return DynamicColorBuilder(
|
return DynamicColorBuilder(
|
||||||
@ -221,13 +232,13 @@ class _ObtainiumState extends State<Obtainium> {
|
|||||||
colorScheme: settingsProvider.theme == ThemeSettings.dark
|
colorScheme: settingsProvider.theme == ThemeSettings.dark
|
||||||
? darkColorScheme
|
? darkColorScheme
|
||||||
: lightColorScheme,
|
: lightColorScheme,
|
||||||
fontFamily: 'Metropolis'),
|
fontFamily: settingsProvider.appFont),
|
||||||
darkTheme: ThemeData(
|
darkTheme: ThemeData(
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
colorScheme: settingsProvider.theme == ThemeSettings.light
|
colorScheme: settingsProvider.theme == ThemeSettings.light
|
||||||
? lightColorScheme
|
? lightColorScheme
|
||||||
: darkColorScheme,
|
: darkColorScheme,
|
||||||
fontFamily: 'Metropolis'),
|
fontFamily: settingsProvider.appFont),
|
||||||
home: Shortcuts(shortcuts: <LogicalKeySet, Intent>{
|
home: Shortcuts(shortcuts: <LogicalKeySet, Intent>{
|
||||||
LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(),
|
LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(),
|
||||||
}, child: const HomePage()));
|
}, child: const HomePage()));
|
||||||
|
@ -351,8 +351,6 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
height16,
|
height16,
|
||||||
installMethodDropdown,
|
|
||||||
height16,
|
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
@ -365,6 +363,7 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
})
|
})
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
installMethodDropdown,
|
||||||
height32,
|
height32,
|
||||||
Text(
|
Text(
|
||||||
tr('sourceSpecific'),
|
tr('sourceSpecific'),
|
||||||
@ -409,6 +408,18 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
height16,
|
height16,
|
||||||
localeDropdown,
|
localeDropdown,
|
||||||
height16,
|
height16,
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Flexible(child: Text(tr('tryUseSystemFont'))),
|
||||||
|
Switch(
|
||||||
|
value: settingsProvider.tryUseSystemFont,
|
||||||
|
onChanged: (value) {
|
||||||
|
settingsProvider.tryUseSystemFont = value;
|
||||||
|
})
|
||||||
|
],
|
||||||
|
),
|
||||||
|
height16,
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
|
@ -33,7 +33,7 @@ import 'package:http/http.dart';
|
|||||||
import 'package:android_intent_plus/android_intent.dart';
|
import 'package:android_intent_plus/android_intent.dart';
|
||||||
import 'package:flutter_archive/flutter_archive.dart';
|
import 'package:flutter_archive/flutter_archive.dart';
|
||||||
import 'package:shared_storage/shared_storage.dart' as saf;
|
import 'package:shared_storage/shared_storage.dart' as saf;
|
||||||
import 'installers_provider.dart';
|
import 'native_provider.dart';
|
||||||
|
|
||||||
final pm = AndroidPackageManager();
|
final pm = AndroidPackageManager();
|
||||||
|
|
||||||
@ -523,12 +523,12 @@ class AppsProvider with ChangeNotifier {
|
|||||||
code = await AndroidPackageInstaller.installApk(
|
code = await AndroidPackageInstaller.installApk(
|
||||||
apkFilePath: file.file.path);
|
apkFilePath: file.file.path);
|
||||||
case InstallMethodSettings.shizuku:
|
case InstallMethodSettings.shizuku:
|
||||||
code = (await Installers.installWithShizuku(
|
code = (await NativeFeatures.installWithShizuku(
|
||||||
apkFileUri: file.file.uri.toString()))
|
apkFileUri: file.file.uri.toString()))
|
||||||
? 0
|
? 0
|
||||||
: 1;
|
: 1;
|
||||||
case InstallMethodSettings.root:
|
case InstallMethodSettings.root:
|
||||||
code = (await Installers.installWithRoot(apkFilePath: file.file.path))
|
code = (await NativeFeatures.installWithRoot(apkFilePath: file.file.path))
|
||||||
? 0
|
? 0
|
||||||
: 1;
|
: 1;
|
||||||
}
|
}
|
||||||
@ -694,14 +694,14 @@ class AppsProvider with ChangeNotifier {
|
|||||||
throw ObtainiumError(tr('cancelled'));
|
throw ObtainiumError(tr('cancelled'));
|
||||||
}
|
}
|
||||||
case InstallMethodSettings.shizuku:
|
case InstallMethodSettings.shizuku:
|
||||||
int code = await Installers.checkPermissionShizuku();
|
int code = await NativeFeatures.checkPermissionShizuku();
|
||||||
if (code == -1) {
|
if (code == -1) {
|
||||||
throw ObtainiumError(tr('shizukuBinderNotFound'));
|
throw ObtainiumError(tr('shizukuBinderNotFound'));
|
||||||
} else if (code == 0) {
|
} else if (code == 0) {
|
||||||
throw ObtainiumError(tr('cancelled'));
|
throw ObtainiumError(tr('cancelled'));
|
||||||
}
|
}
|
||||||
case InstallMethodSettings.root:
|
case InstallMethodSettings.root:
|
||||||
if (!(await Installers.checkPermissionRoot())) {
|
if (!(await NativeFeatures.checkPermissionRoot())) {
|
||||||
throw ObtainiumError(tr('cancelled'));
|
throw ObtainiumError(tr('cancelled'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,25 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
class Installers {
|
class NativeFeatures {
|
||||||
static const MethodChannel _channel = MethodChannel('installers');
|
static const MethodChannel _channel = MethodChannel('native');
|
||||||
static bool _callbacksApplied = false;
|
static bool _callbacksApplied = false;
|
||||||
static int _resPermShizuku = -2; // not set
|
static int _resPermShizuku = -2; // not set
|
||||||
|
|
||||||
static Future waitWhile(bool Function() test,
|
static Future<ByteData> _readFileBytes(String path) async {
|
||||||
|
var file = File(path);
|
||||||
|
var bytes = await file.readAsBytes();
|
||||||
|
return ByteData.view(bytes.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future _handleCalls(MethodCall call) async {
|
||||||
|
if (call.method == 'resPermShizuku') {
|
||||||
|
_resPermShizuku = call.arguments['res'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future _waitWhile(bool Function() test,
|
||||||
[Duration pollInterval = const Duration(milliseconds: 250)]) {
|
[Duration pollInterval = const Duration(milliseconds: 250)]) {
|
||||||
var completer = Completer();
|
var completer = Completer();
|
||||||
check() {
|
check() {
|
||||||
@ -20,20 +33,23 @@ class Installers {
|
|||||||
return completer.future;
|
return completer.future;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future handleCalls(MethodCall call) async {
|
static Future<bool> tryLoadSystemFont() async {
|
||||||
if (call.method == 'resPermShizuku') {
|
var font = await _channel.invokeMethod('getSystemFont');
|
||||||
_resPermShizuku = call.arguments['res'];
|
if (font == null) { return false; }
|
||||||
}
|
var fontLoader = FontLoader('SystemFont');
|
||||||
|
fontLoader.addFont(_readFileBytes(font));
|
||||||
|
await fontLoader.load();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<int> checkPermissionShizuku() async {
|
static Future<int> checkPermissionShizuku() async {
|
||||||
if (!_callbacksApplied) {
|
if (!_callbacksApplied) {
|
||||||
_channel.setMethodCallHandler(handleCalls);
|
_channel.setMethodCallHandler(_handleCalls);
|
||||||
_callbacksApplied = true;
|
_callbacksApplied = true;
|
||||||
}
|
}
|
||||||
int res = await _channel.invokeMethod('checkPermissionShizuku');
|
int res = await _channel.invokeMethod('checkPermissionShizuku');
|
||||||
if(res == -2) {
|
if (res == -2) {
|
||||||
await waitWhile(() => _resPermShizuku == -2);
|
await _waitWhile(() => _resPermShizuku == -2);
|
||||||
res = _resPermShizuku;
|
res = _resPermShizuku;
|
||||||
_resPermShizuku = -2;
|
_resPermShizuku = -2;
|
||||||
}
|
}
|
@ -51,6 +51,24 @@ class SettingsProvider with ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String get appFont {
|
||||||
|
return prefs?.getString('appFont') ?? 'Metropolis';
|
||||||
|
}
|
||||||
|
|
||||||
|
set appFont(String appFont) {
|
||||||
|
prefs?.setString('appFont', appFont);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get tryUseSystemFont {
|
||||||
|
return prefs?.getBool('tryUseSystemFont') ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
set tryUseSystemFont(bool tryUseSystemFont) {
|
||||||
|
prefs?.setBool('tryUseSystemFont', tryUseSystemFont);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
InstallMethodSettings get installMethod {
|
InstallMethodSettings get installMethod {
|
||||||
return InstallMethodSettings
|
return InstallMethodSettings
|
||||||
.values[prefs?.getInt('installMethod') ?? InstallMethodSettings.normal.index];
|
.values[prefs?.getInt('installMethod') ?? InstallMethodSettings.normal.index];
|
||||||
|
Reference in New Issue
Block a user