Merge pull request #242 from chenguangming/master

适配Android14对截屏的严格要求
This commit is contained in:
SuperMonster003
2024-09-01 16:34:57 +08:00
committed by GitHub
6 changed files with 38 additions and 11 deletions

View File

@@ -122,6 +122,8 @@
<uses-permission android:name="android.permission.READ_SMS" /> <uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
<!-- Property "largeHeap" is not recommended to set to true. --> <!-- Property "largeHeap" is not recommended to set to true. -->
<!-- https://stackoverflow.com/questions/27396892/what-are-advantages-of-setting-largeheap-to-true --> <!-- https://stackoverflow.com/questions/27396892/what-are-advantages-of-setting-largeheap-to-true -->
<application <application
@@ -130,7 +132,7 @@
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:icon="${icon}" android:icon="${icon}"
android:label="${appName}" android:label="${appName}"
android:largeHeap="false" android:largeHeap="true"
android:requestLegacyExternalStorage="true" android:requestLegacyExternalStorage="true"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"

View File

@@ -6,6 +6,7 @@ import android.content.Intent;
import android.media.projection.MediaProjectionManager; import android.media.projection.MediaProjectionManager;
import org.autojs.autojs.app.OnActivityResultDelegate; import org.autojs.autojs.app.OnActivityResultDelegate;
import org.autojs.autojs.util.ForegroundServiceUtils;
/** /**
* Created by Stardust on May 17, 2017. * Created by Stardust on May 17, 2017.
@@ -46,9 +47,18 @@ public interface ScreenCaptureRequester {
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
mResult = data; mResult = data;
mMediator.removeDelegate(this); mMediator.removeDelegate(this);
onResult(resultCode, data); // 按照官方文档https://developer.android.com/reference/android/media/projection/MediaProjectionManager启动媒体投影的示例流程如下
} // 1. AndroidManifest.xml声明mediaProjection类型前台服务
// 2. 通过调用MediaProjectionManager#createScreenCaptureIntent()创建intent并传递给Activity#startActivityForResult(Intent, int)
// 3. 在得到用户授权后回调Activity#onActivityResult中使用 ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION类型 启动前台服务
// 4. 再通过MediaProjectionManager#getMediaProjection(int, Intent)得到MediaProjection
// 5. 通过MediaProjection#createVirtualDisplay调用启动媒体投影的屏幕捕获会话
// 总结就是,要保证:先授权,再启动服务,再录屏的顺序
// 原代码在ScreenCaptureRequesterImpl#requst中startService会有时序问题此时用户还没授权完成时Android 14+启动前台服务实测会崩溃
// 改成bindService并等待onServiceConnected回调
ForegroundServiceUtils.requestReadyIfNeeded(mActivity.getApplicationContext(), ScreenCapturerForegroundService.class, () -> onResult(resultCode, data));
}
} }
abstract class AbstractScreenCaptureRequester implements ScreenCaptureRequester { abstract class AbstractScreenCaptureRequester implements ScreenCaptureRequester {
@@ -75,7 +85,5 @@ public interface ScreenCaptureRequester {
if (mCallback != null) if (mCallback != null)
mCallback.onRequestResult(Activity.RESULT_CANCELED, null); mCallback.onRequestResult(Activity.RESULT_CANCELED, null);
} }
} }
} }

View File

@@ -4,7 +4,6 @@ import android.app.Activity;
import org.autojs.autojs.AbstractAutoJs; import org.autojs.autojs.AbstractAutoJs;
import org.autojs.autojs.app.OnActivityResultDelegate; import org.autojs.autojs.app.OnActivityResultDelegate;
import org.autojs.autojs.util.ForegroundServiceUtils;
public class ScreenCaptureRequesterImpl extends ScreenCaptureRequester.AbstractScreenCaptureRequester { public class ScreenCaptureRequesterImpl extends ScreenCaptureRequester.AbstractScreenCaptureRequester {
@@ -25,8 +24,6 @@ public class ScreenCaptureRequesterImpl extends ScreenCaptureRequester.AbstractS
@Override @Override
public void request() { public void request() {
ForegroundServiceUtils.requestIfNeeded(mAutoJs.getApplicationContext(), ScreenCapturerForegroundService.class);
Activity activity = mAutoJs.getAppUtils().getCurrentActivity(); Activity activity = mAutoJs.getAppUtils().getCurrentActivity();
if (activity instanceof OnActivityResultDelegate.DelegateHost) { if (activity instanceof OnActivityResultDelegate.DelegateHost) {

View File

@@ -4,6 +4,7 @@ import android.app.Service;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo;
import android.os.Binder;
import android.os.Build; import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
@@ -38,7 +39,7 @@ public class ScreenCapturerForegroundService extends Service {
@Nullable @Nullable
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
return null; return new Binder();
} }
private void startForeground() { private void startForeground() {

View File

@@ -33,7 +33,7 @@ class MainActivityForegroundService : Service() {
.create() .create()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
ForegroundServiceUtils.startForeground(foregroundServiceCreator, ServiceInfo.FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED) ForegroundServiceUtils.startForeground(foregroundServiceCreator, ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE)
} else { } else {
ForegroundServiceUtils.startForeground(foregroundServiceCreator) ForegroundServiceUtils.startForeground(foregroundServiceCreator)
} }

View File

@@ -6,10 +6,12 @@ import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.Service; import android.app.Service;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ServiceInfo; import android.content.ServiceConnection;
import android.os.Build; import android.os.Build;
import android.os.IBinder;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@@ -36,6 +38,23 @@ public class ForegroundServiceUtils {
} }
} }
public static void requestReadyIfNeeded(Context context, Class<?> className, Runnable runnable) {
if (isRunning(context, className)) {
runnable.run();
} else {
context.bindService(getService(context, className), new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
runnable.run();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}, Context.BIND_AUTO_CREATE);
}
}
public static boolean startService(Context context, Class<?> className) { public static boolean startService(Context context, Class<?> className) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return context.startForegroundService(getService(context, className)) != null; return context.startForegroundService(getService(context, className)) != null;