mirror of
https://github.com/QM4RS/FridaBox.git
synced 2026-10-17 21:32:11 +02:00
feat: Implement legacy storage permission handling for Android 10 and below, and improve compatibility by fixing service hook and attribution source issues.
This commit is contained in:
@@ -50,6 +50,10 @@ public abstract class ClassInvocationStub implements InvocationHandler, IInjectH
|
||||
@Override
|
||||
public void injectHook() {
|
||||
mBase = getWho();
|
||||
// Skip hook if service doesn't exist on this Android version
|
||||
if (mBase == null) {
|
||||
return;
|
||||
}
|
||||
mProxyInvocation = Proxy.newProxyInstance(mBase.getClass().getClassLoader(), MethodParameterUtils.getAllInterface(mBase.getClass()), this);
|
||||
if (!onlyProxy) {
|
||||
inject(mBase, mProxyInvocation);
|
||||
|
||||
@@ -91,7 +91,7 @@ import top.niunaijun.blackbox.utils.compat.BuildCompat;
|
||||
import top.niunaijun.blackbox.fake.service.ISettingsProviderProxy;
|
||||
import top.niunaijun.blackbox.fake.service.FeatureFlagUtilsProxy;
|
||||
import top.niunaijun.blackbox.fake.service.WorkManagerProxy;
|
||||
import top.niunaijun.blackbox.fake.service.IInputMethodManagerProxy;
|
||||
// Removed IInputMethodManagerProxy - causes ClassCastException on Android 15
|
||||
|
||||
/**
|
||||
* updated by alex5402 on 3/30/21.
|
||||
@@ -177,7 +177,7 @@ public class HookManager {
|
||||
addInjector(new IMediaRouterServiceProxy());
|
||||
addInjector(new IPowerManagerProxy());
|
||||
addInjector(new IContextHubServiceProxy());
|
||||
addInjector(new IInputMethodManagerProxy());
|
||||
// Removed IInputMethodManagerProxy - causes ClassCastException on Android 15 due to queryLocalInterface returning non-IInterface proxy
|
||||
addInjector(new IVibratorServiceProxy());
|
||||
addInjector(new IPersistentDataBlockServiceProxy());
|
||||
addInjector(AppInstrumentation.get());
|
||||
|
||||
+10
-3
@@ -60,9 +60,12 @@ public class SystemProviderStub extends ClassInvocationStub implements BContentP
|
||||
if ("call".equals(methodName)) {
|
||||
// Only fix AttributionSource in call() args, don't replace method name
|
||||
if (args != null) {
|
||||
Class<?> attributionSourceClass = BRAttributionSource.getRealClass();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
Object arg = args[i];
|
||||
if (arg != null && arg.getClass().getName().equals(BRAttributionSource.getRealClass().getName())) {
|
||||
// Check for null - AttributionSource doesn't exist on Android < S (31)
|
||||
if (arg != null && attributionSourceClass != null &&
|
||||
arg.getClass().getName().equals(attributionSourceClass.getName())) {
|
||||
ContextCompat.fixAttributionSourceState(arg, BlackBoxCore.getHostUid());
|
||||
}
|
||||
}
|
||||
@@ -79,8 +82,12 @@ public class SystemProviderStub extends ClassInvocationStub implements BContentP
|
||||
if (!isSystemProviderAuthority(authority)) {
|
||||
args[0] = BlackBoxCore.getHostPkg();
|
||||
}
|
||||
} else if (arg != null && arg.getClass().getName().equals(BRAttributionSource.getRealClass().getName())) {
|
||||
ContextCompat.fixAttributionSourceState(arg, BlackBoxCore.getHostUid());
|
||||
} else if (arg != null) {
|
||||
Class<?> attrSourceClass = BRAttributionSource.getRealClass();
|
||||
// Check for null - AttributionSource doesn't exist on Android < S (31)
|
||||
if (attrSourceClass != null && arg.getClass().getName().equals(attrSourceClass.getName())) {
|
||||
ContextCompat.fixAttributionSourceState(arg, BlackBoxCore.getHostUid());
|
||||
}
|
||||
}
|
||||
}
|
||||
return method.invoke(mBase, args);
|
||||
|
||||
@@ -6,6 +6,12 @@
|
||||
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
|
||||
tools:ignore="QueryAllPackagesPermission" />
|
||||
|
||||
<!-- Storage permissions for Android 10 and below -->
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="29" />
|
||||
|
||||
|
||||
<application
|
||||
android:name=".app.App"
|
||||
android:allowBackup="true"
|
||||
|
||||
@@ -37,6 +37,7 @@ class MainActivity : LoadingActivity() {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "MainActivity"
|
||||
private const val STORAGE_PERMISSION_REQUEST_CODE = 1001
|
||||
|
||||
fun start(context: Context) {
|
||||
val intent = Intent(context, MainActivity::class.java)
|
||||
@@ -78,16 +79,68 @@ class MainActivity : LoadingActivity() {
|
||||
private fun checkStoragePermission() {
|
||||
try {
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
|
||||
// Android 11+: Need MANAGE_EXTERNAL_STORAGE
|
||||
if (!android.os.Environment.isExternalStorageManager()) {
|
||||
Log.w(TAG, "MANAGE_EXTERNAL_STORAGE permission not granted")
|
||||
showStoragePermissionDialog()
|
||||
}
|
||||
} else {
|
||||
// Android 10 and below: Need READ/WRITE_EXTERNAL_STORAGE
|
||||
if (androidx.core.content.ContextCompat.checkSelfPermission(
|
||||
this,
|
||||
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
) != android.content.pm.PackageManager.PERMISSION_GRANTED ||
|
||||
androidx.core.content.ContextCompat.checkSelfPermission(
|
||||
this,
|
||||
android.Manifest.permission.READ_EXTERNAL_STORAGE
|
||||
) != android.content.pm.PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
Log.w(
|
||||
TAG,
|
||||
"Storage permissions not granted on Android ${android.os.Build.VERSION.SDK_INT}"
|
||||
)
|
||||
requestLegacyStoragePermission()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error checking storage permission: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestLegacyStoragePermission() {
|
||||
try {
|
||||
androidx.core.app.ActivityCompat.requestPermissions(
|
||||
this,
|
||||
arrayOf(
|
||||
android.Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
),
|
||||
STORAGE_PERMISSION_REQUEST_CODE
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error requesting storage permission: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<out String>,
|
||||
grantResults: IntArray
|
||||
) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
if (requestCode == STORAGE_PERMISSION_REQUEST_CODE) {
|
||||
if (grantResults.isNotEmpty() &&
|
||||
grantResults.all {
|
||||
it == android.content.pm.PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
) {
|
||||
Log.d(TAG, "Storage permissions granted")
|
||||
} else {
|
||||
Log.w(TAG, "Storage permissions denied")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showStoragePermissionDialog() {
|
||||
try {
|
||||
MaterialDialog(this).show {
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ ext {
|
||||
// targetSdkVersion = 35
|
||||
minSdk = 21
|
||||
versionCode = 1
|
||||
versionName = "3.0.13-beta2"
|
||||
versionName = "3.1.0-beta"
|
||||
xVersion = '1.1.0'
|
||||
hiddenApiBypass = '4.3'
|
||||
}
|
||||
Reference in New Issue
Block a user