修复已知问题

This commit is contained in:
TonyJiangWJ 2022-01-25 20:07:40 +08:00
parent 00aa9fe0aa
commit 6f124ded16
8 changed files with 81 additions and 26 deletions

View File

@ -263,6 +263,9 @@ public abstract class AutoJs {
@Override
public void request() {
Activity activity = mAppUtils.getCurrentActivity();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
mContext.startForegroundService(new Intent(mContext, CaptureForegroundService.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
if (activity instanceof OnActivityResultDelegate.DelegateHost) {
ScreenCaptureRequester requester = new ActivityScreenCaptureRequester(
((OnActivityResultDelegate.DelegateHost) activity).getOnActivityResultDelegateMediator(), activity);

View File

@ -11,6 +11,7 @@ import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
@ -22,6 +23,7 @@ public class CaptureForegroundService extends Service {
private static final int NOTIFICATION_ID = 2;
private static final String CHANNEL_ID = CaptureForegroundService.class.getName() + ".foreground";
private final String TAG = "CaptureForegrdService";
@Nullable
@Override
@ -31,6 +33,9 @@ public class CaptureForegroundService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
startForeground(NOTIFICATION_ID, buildNotification());
GlobalScreenCapture.getInstance().notifyStarted();
return super.onStartCommand(intent, flags, startId);
}
@ -38,6 +43,7 @@ public class CaptureForegroundService extends Service {
public void onCreate() {
super.onCreate();
startForeground(NOTIFICATION_ID, buildNotification());
GlobalScreenCapture.getInstance().notifyStarted();
}
private Notification buildNotification() {
@ -46,7 +52,12 @@ public class CaptureForegroundService extends Service {
}
int flags = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? FLAG_IMMUTABLE : 0;
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, ScreenCaptureRequestActivity.class), flags);
Log.d(TAG, "buildNotification: start");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager notificationManager = (NotificationManager) this.getSystemService(NOTIFICATION_SERVICE);
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, "Recording", NotificationManager.IMPORTANCE_MIN);
notificationManager.createNotificationChannel(notificationChannel);
}
return new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Recording")
.setContentText("本通知为截图权限需要")
@ -55,6 +66,7 @@ public class CaptureForegroundService extends Service {
.setContentIntent(contentIntent)
.setChannelId(CHANNEL_ID)
.setVibrate(new long[0])
.setDefaults(Notification.DEFAULT_ALL | NotificationCompat.FLAG_ONLY_ALERT_ONCE)
.build();
}

View File

@ -17,8 +17,6 @@ import android.os.Looper;
import android.util.Log;
import android.view.OrientationEventListener;
import androidx.annotation.Nullable;
import com.stardust.autojs.runtime.exception.ScriptException;
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
import com.stardust.lang.ThreadCompat;
@ -28,6 +26,8 @@ import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import androidx.annotation.Nullable;
/**
* Created by TonyJiangWJ on 2022/1/22
*/
@ -50,8 +50,9 @@ public class GlobalScreenCapture {
private Handler mHandler;
private final AtomicReference<Image> mCachedImage = new AtomicReference<>();
private volatile Exception mException;
private boolean foregroundServiceStarted = false;
private final int mScreenDensity;
private int mScreenDensity;
private int mOrientation = -1;
private int mDetectedOrientation;
private OrientationEventListener mOrientationEventListener;
@ -59,28 +60,43 @@ public class GlobalScreenCapture {
private boolean hasPermission;
private boolean noRegister;
@SuppressLint("StaticFieldLeak")
private static volatile GlobalScreenCapture INSTANCE;
private GlobalScreenCapture() {
mScreenDensity = ScreenMetrics.getDeviceScreenDensity();
}
private static class Holder {
@SuppressLint("StaticFieldLeak")
private final static GlobalScreenCapture INSTANCE = new GlobalScreenCapture();
}
public static GlobalScreenCapture getInstance() {
return Holder.INSTANCE;
if (INSTANCE == null) {
synchronized (GlobalScreenCapture.class) {
if (INSTANCE == null) {
INSTANCE = new GlobalScreenCapture();
}
}
}
return INSTANCE;
}
public synchronized void initCapture(Context context, Intent data, int orientation) {
Log.d(TAG, "initCapture: ");
Log.d(TAG, "initCapture: " + mScreenDensity);
if (mScreenDensity == 0) {
mScreenDensity = ScreenMetrics.getDeviceScreenDensity();
}
if (!foregroundServiceStarted) {
try {
this.wait();
} catch (InterruptedException e) {
throw new ScriptInterruptedException();
}
}
mProjectionManager = (MediaProjectionManager) context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
mMediaProjection = mProjectionManager.getMediaProjection(Activity.RESULT_OK, (Intent) data.clone());
mContext = context;
mData = (Intent) data.clone();
new Thread(() -> {
Looper.prepare();
mHandler = new Handler(Looper.myLooper());
mHandler = new Handler(Looper.getMainLooper());
synchronized (GlobalScreenCapture.this) {
GlobalScreenCapture.this.notifyAll();
}
@ -98,6 +114,11 @@ public class GlobalScreenCapture {
hasPermission = true;
}
public synchronized void notifyStarted() {
this.foregroundServiceStarted = true;
this.notify();
}
public synchronized boolean hasPermission() {
return hasPermission;
}
@ -144,19 +165,26 @@ public class GlobalScreenCapture {
if (mVirtualDisplay != null) {
mVirtualDisplay.release();
}
try {
mMediaProjection = mProjectionManager.getMediaProjection(Activity.RESULT_OK, (Intent) mData.clone());
} catch (Exception e) {
Log.d(TAG, "refreshVirtualDisplay: 获取新projection失败 可能只是MIUI的bug " + e);
}
int screenHeight = ScreenMetrics.getOrientationAwareScreenHeight(orientation);
int screenWidth = ScreenMetrics.getOrientationAwareScreenWidth(orientation);
initVirtualDisplay(screenWidth, screenHeight, mScreenDensity);
startAcquireImageLoop();
}
private void grantMediaProjection() {
try {
if (mMediaProjection != null) {
mMediaProjection.stop();
}
mMediaProjection = mProjectionManager.getMediaProjection(Activity.RESULT_OK, (Intent) mData.clone());
} catch (Exception e) {
Log.d(TAG, "grantMediaProjection: 获取新projection失败 可能只是MIUI的bug " + e);
}
}
@SuppressLint("WrongConstant")
private void initVirtualDisplay(int width, int height, int screenDensity) {
Log.d(TAG, "initVirtualDisplay: width:" + width + ",height:" + height + ",density:" + screenDensity);
mImageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 3);
try {
mVirtualDisplay = mMediaProjection.createVirtualDisplay(TAG,
@ -217,6 +245,7 @@ public class GlobalScreenCapture {
if (System.currentTimeMillis() - startTime > 1000) {
startTime = System.currentTimeMillis();
Log.d(TAG, "capture: 获取截图失败刷新virtualDisplay");
this.grantMediaProjection();
this.refreshVirtualDisplay(mOrientation);
}
}
@ -250,6 +279,7 @@ public class GlobalScreenCapture {
noRegister = true;
hasPermission = false;
mOrientation = -1;
foregroundServiceStarted = false;
if (mImageAcquireLooper != null) {
mImageAcquireLooper.quit();
mImageAcquireLooper = null;

View File

@ -23,9 +23,6 @@ public class ScreenCaptureRequestActivity extends Activity {
private ScreenCaptureRequester.Callback mCallback;
public static void request(Context context, ScreenCaptureRequester.Callback callback) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
context.startForegroundService(new Intent(context, CaptureForegroundService.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
Intent intent = new Intent(context, ScreenCaptureRequestActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
IntentExtras.newExtras()

View File

@ -79,9 +79,6 @@ public interface ScreenCaptureRequester {
@Override
public void request() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
mActivity.startForegroundService(new Intent(mActivity, CaptureForegroundService.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
mActivity.startActivityForResult(((MediaProjectionManager) mActivity.getSystemService(Context.MEDIA_PROJECTION_SERVICE)).createScreenCaptureIntent(), REQUEST_CODE_MEDIA_PROJECTION);
}

View File

@ -1,5 +1,8 @@
package com.stardust.autojs.core.util
import android.util.Log
import com.stardust.concurrent.VolatileDispose
class ScriptPromiseAdapter {
interface Callback {
@ -10,17 +13,25 @@ class ScriptPromiseAdapter {
private var mRejectCallback: Callback? = null
private var mResult: Any? = UNSET
private var mError: Any? = UNSET
private val TAG = "ScriptPromiseAdapter";
private var volatileDispose = VolatileDispose<Boolean>();
fun onResolve(callback: Callback): ScriptPromiseAdapter {
Log.d(TAG, "onResolve, mResult == UNSET ? " + (mResult == UNSET))
mResolveCallback = callback
mResult.let {
if (it !== UNSET) {
callback.call(it)
}
}
volatileDispose.setAndNotify(true)
return this
}
fun awaitResolver() {
volatileDispose.blockedGet()
}
fun onReject(callback: Callback): ScriptPromiseAdapter {
mRejectCallback = callback
mError.let {
@ -32,6 +43,7 @@ class ScriptPromiseAdapter {
}
fun resolve(result: Any?) {
Log.d(TAG, "resolve, result = " + result)
mResult = result
mResolveCallback?.call(result)
releaseCallbacks()

View File

@ -13,7 +13,7 @@ public class DeleteOnFinalizeFile {
public DeleteOnFinalizeFile(File file) {
fileObject = file;
}
/*
@Override
protected void finalize() throws Throwable {
super.finalize();
@ -23,4 +23,5 @@ public class DeleteOnFinalizeFile {
fileObject.delete();
}
}
*/
}

View File

@ -84,8 +84,11 @@ public class Images {
Log.d(TAG, "requestScreenCapture hasPermission 直接注册");
GlobalScreenCapture.getInstance().setOrientation(orientation);
GlobalScreenCapture.getInstance().register(mScriptRuntime.get().loopers.getMainLooper());
new Handler(mScriptRuntime.get().loopers.getMainLooper())
.post(() -> promiseAdapter.resolve(true));
new Handler(Looper.getMainLooper())
.post(() -> {
promiseAdapter.awaitResolver();
promiseAdapter.resolve(true);
});
return promiseAdapter;
}
}