|
|
@@ -19,17 +19,22 @@ import android.os.Build;
|
|
|
import android.os.Handler;
|
|
|
import android.os.IBinder;
|
|
|
import android.os.Message;
|
|
|
-import android.util.Log;
|
|
|
+import android.os.SystemClock;
|
|
|
+import android.util.DisplayMetrics;
|
|
|
+import android.view.Display;
|
|
|
+import android.view.GestureDetector;
|
|
|
import android.view.Gravity;
|
|
|
import android.view.MotionEvent;
|
|
|
import android.view.View;
|
|
|
import android.view.WindowManager;
|
|
|
import android.widget.ImageView;
|
|
|
|
|
|
-import com.sheep.gamegroup.model.entity.TaskAcceptedEty;
|
|
|
import com.sheep.gamegroup.util.DataUtil;
|
|
|
import com.sheep.gamegroup.util.GlobalScreenShot;
|
|
|
+import com.sheep.gamegroup.util.LogUtil;
|
|
|
+import com.sheep.gamegroup.view.activity.MiddleScreenShotAct;
|
|
|
import com.sheep.jiuyan.samllsheep.R;
|
|
|
+import com.sheep.jiuyan.samllsheep.SheepApp;
|
|
|
import com.sheep.jiuyan.samllsheep.utils.G;
|
|
|
|
|
|
import java.io.File;
|
|
|
@@ -44,7 +49,6 @@ import rx.functions.Action1;
|
|
|
import rx.functions.Func1;
|
|
|
import rx.schedulers.Schedulers;
|
|
|
|
|
|
-import static com.sheep.gamegroup.util.DataUtil.REQUEST_CAPTURE_PERMISSION;
|
|
|
|
|
|
/**
|
|
|
* Created by realicing on 2018/5/8.
|
|
|
@@ -58,12 +62,17 @@ public class FloatShotScreenService extends Service {
|
|
|
public IBinder onBind(Intent intent) {
|
|
|
return null;
|
|
|
}
|
|
|
+ private static FloatShotScreenService instance;
|
|
|
+
|
|
|
+ public static FloatShotScreenService getInstance() {
|
|
|
+ return instance;
|
|
|
+ }
|
|
|
|
|
|
@Override
|
|
|
public void onCreate() {
|
|
|
super.onCreate();
|
|
|
+ instance = this;
|
|
|
createFloatView();
|
|
|
- createImageReader();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -73,7 +82,7 @@ public class FloatShotScreenService extends Service {
|
|
|
if (floatView != null) {
|
|
|
try {
|
|
|
if(isAdded)
|
|
|
- wm.removeViewImmediate(floatView);
|
|
|
+ windowManager.removeViewImmediate(floatView);
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
@@ -83,15 +92,16 @@ public class FloatShotScreenService extends Service {
|
|
|
tearDownMediaProjection();
|
|
|
}
|
|
|
|
|
|
- // public static final String OPERATION = "operation";
|
|
|
public static final int OPERATION_SHOW = 100;
|
|
|
public static final int OPERATION_HIDE = 101;
|
|
|
+ public static final int SCREEN_SHOT = 1;//截图回调
|
|
|
+ public static final int SET_SHOW_OR_HIDE = 2;//设置显示或不显示
|
|
|
|
|
|
private static final int HANDLE_CHECK_ACTIVITY = 200;
|
|
|
|
|
|
private boolean isAdded = false; // 是否已增加悬浮窗
|
|
|
- private static WindowManager wm;
|
|
|
- private static WindowManager.LayoutParams params;
|
|
|
+ private WindowManager windowManager;
|
|
|
+ private WindowManager.LayoutParams params;
|
|
|
private View floatView;
|
|
|
|
|
|
|
|
|
@@ -100,11 +110,10 @@ public class FloatShotScreenService extends Service {
|
|
|
if (intent != null) {
|
|
|
int type = intent.getIntExtra("type", 0);
|
|
|
switch (type) {
|
|
|
- case 1:
|
|
|
- mResultData = (Intent) DataUtil.getInstance().getData(REQUEST_CAPTURE_PERMISSION);
|
|
|
+ case SCREEN_SHOT:
|
|
|
+ performClick();
|
|
|
break;
|
|
|
- case 0:
|
|
|
- default:
|
|
|
+ case SET_SHOW_OR_HIDE:
|
|
|
if (intent.getBooleanExtra("isShow", true)) {
|
|
|
mHandler.sendEmptyMessageDelayed(OPERATION_SHOW, 1000L);
|
|
|
} else {
|
|
|
@@ -112,6 +121,8 @@ public class FloatShotScreenService extends Service {
|
|
|
mHandler.sendEmptyMessage(OPERATION_HIDE);
|
|
|
}
|
|
|
break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
return super.onStartCommand(intent, flags, startId);
|
|
|
@@ -138,8 +149,9 @@ public class FloatShotScreenService extends Service {
|
|
|
if (!service.isAdded) {
|
|
|
try {
|
|
|
// service.floatView.setAlpha(1.0f);
|
|
|
-// wm.updateViewLayout(service.floatView, params);
|
|
|
- wm.addView(service.floatView, params);
|
|
|
+// windowManager.updateViewLayout(service.floatView, params);
|
|
|
+ service.resetParams();
|
|
|
+ service.windowManager.addView(service.floatView, service.params);
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
@@ -151,8 +163,8 @@ public class FloatShotScreenService extends Service {
|
|
|
if (service.isAdded) {
|
|
|
try {
|
|
|
// service.floatView.setAlpha(0.0f);
|
|
|
-// wm.updateViewLayout(service.floatView, params);
|
|
|
- wm.removeViewImmediate(service.floatView);
|
|
|
+// windowManager.updateViewLayout(service.floatView, params);
|
|
|
+ service.windowManager.removeViewImmediate(service.floatView);
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
@@ -173,7 +185,7 @@ public class FloatShotScreenService extends Service {
|
|
|
imageView.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_crop));
|
|
|
floatView = imageView;
|
|
|
|
|
|
- wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
|
|
|
+ windowManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
|
|
|
params = new WindowManager.LayoutParams();
|
|
|
|
|
|
// 设置window type
|
|
|
@@ -184,12 +196,12 @@ public class FloatShotScreenService extends Service {
|
|
|
// }
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
|
// 大于等于 24 即为 7.0 及以上执行内容
|
|
|
- Log.e("qx", "7.0");
|
|
|
+// Log.e("qx", "7.0");
|
|
|
params.type = WindowManager.LayoutParams.TYPE_PHONE; // 7.1
|
|
|
} else {
|
|
|
// 低于 24 即为 7.0 以下执行内容
|
|
|
params.type = WindowManager.LayoutParams.TYPE_TOAST; // 4.4
|
|
|
- Log.e("qx", "4.4");
|
|
|
+// Log.e("qx", "4.4");
|
|
|
|
|
|
}
|
|
|
/*
|
|
|
@@ -204,111 +216,87 @@ public class FloatShotScreenService extends Service {
|
|
|
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
|
|
// 设置悬浮窗的Touch监听
|
|
|
floatView.setOnTouchListener(new View.OnTouchListener() {
|
|
|
- int lastX, lastY;
|
|
|
- int paramX, paramY;
|
|
|
- private boolean isMove = false;
|
|
|
- private long downTime = 0;
|
|
|
-
|
|
|
+ GestureDetector mGestureDetector = new GestureDetector(getApplicationContext(), new FloatGestureTouchListener());
|
|
|
+ @Override
|
|
|
public boolean onTouch(View v, MotionEvent event) {
|
|
|
- switch (event.getAction()) {
|
|
|
- case MotionEvent.ACTION_DOWN:
|
|
|
- isMove = false;
|
|
|
- downTime = System.currentTimeMillis();
|
|
|
- lastX = (int) event.getRawX();
|
|
|
- lastY = (int) event.getRawY();
|
|
|
- paramX = params.x;
|
|
|
- paramY = params.y;
|
|
|
- break;
|
|
|
- case MotionEvent.ACTION_MOVE:
|
|
|
- int dx = (int) event.getRawX() - lastX;
|
|
|
- int dy = (int) event.getRawY() - lastY;
|
|
|
- params.x = paramX + dx;
|
|
|
- params.y = paramY + dy;
|
|
|
- // 更新悬浮窗位置
|
|
|
- wm.updateViewLayout(floatView, params);
|
|
|
- isMove = true;
|
|
|
- break;
|
|
|
- case MotionEvent.ACTION_UP:
|
|
|
- if (!isMove && System.currentTimeMillis() - downTime < 1000L) {//没有移动过并且小于1秒就弹起来就点击
|
|
|
- performClick();
|
|
|
- }
|
|
|
- isMove = false;
|
|
|
- break;
|
|
|
- }
|
|
|
- return false;
|
|
|
+ if(event == null)
|
|
|
+ v.performClick();
|
|
|
+ return mGestureDetector.onTouchEvent(event);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
+// resetParams();
|
|
|
+//
|
|
|
+// try {
|
|
|
+// windowManager.addView(floatView, params);
|
|
|
+// isAdded = true;
|
|
|
+// } catch (Exception e) {
|
|
|
+// e.printStackTrace();
|
|
|
+// }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void resetParams() {
|
|
|
+ Display display = windowManager.getDefaultDisplay();
|
|
|
+ DisplayMetrics metric = new DisplayMetrics();
|
|
|
+ display.getMetrics(metric);
|
|
|
// 设置悬浮窗的长得宽
|
|
|
- params.width = WindowManager.LayoutParams.WRAP_CONTENT;
|
|
|
+ params.width = SheepApp.getInstance().getResources().getDimensionPixelSize(R.dimen.content_padding_30);
|
|
|
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
|
|
params.gravity = Gravity.START | Gravity.TOP;
|
|
|
- params.x = G.WIDTH;
|
|
|
- params.y = 100;
|
|
|
-
|
|
|
- try {
|
|
|
- wm.addView(floatView, params);
|
|
|
- isAdded = true;
|
|
|
- } catch (Exception e) {
|
|
|
- e.printStackTrace();
|
|
|
- }
|
|
|
+ params.x = metric.widthPixels;
|
|
|
+ params.y = SheepApp.getInstance().getResources().getDimensionPixelSize(R.dimen.content_padding_100);
|
|
|
}
|
|
|
|
|
|
private void performClick() {
|
|
|
//获取当前正在运行的程序的包名
|
|
|
- String packageName = DataUtil.getInstance().getPackageNameInForeground();
|
|
|
- if(DataUtil.getInstance().getTaskAcceptedEtyFromPackageName(packageName) == null){
|
|
|
- //TODO 如果一个任务需要截取其它程序的截图,这里就不行了:如收到的短信
|
|
|
- G.showToast("请切换到对应的应用后进行截图!");
|
|
|
- return;
|
|
|
- }
|
|
|
- packageNameInForeground = packageName;
|
|
|
+ //不判断是否是正在进行的任务上截图,只在上传截图的地方获取指定包名的截图
|
|
|
+ packageNameInForeground = DataUtil.getInstance().getPackageNameInForeground();
|
|
|
// 设置点击悬浮窗的响应
|
|
|
startScreenShot();
|
|
|
}
|
|
|
private String packageNameInForeground;
|
|
|
|
|
|
private void startScreenShot() {
|
|
|
-
|
|
|
- floatView.setVisibility(View.GONE);
|
|
|
-
|
|
|
Handler handler1 = new Handler();
|
|
|
handler1.postDelayed(new Runnable() {
|
|
|
public void run() {
|
|
|
- //start virtual
|
|
|
- startVirtual();
|
|
|
+ floatView.setVisibility(View.GONE);
|
|
|
}
|
|
|
- }, 5);
|
|
|
-
|
|
|
+ }, 0);
|
|
|
handler1.postDelayed(new Runnable() {
|
|
|
public void run() {
|
|
|
- //capture the screen
|
|
|
- startCapture();
|
|
|
-
|
|
|
+ //start virtual
|
|
|
+ startVirtual();
|
|
|
}
|
|
|
- }, 30);
|
|
|
+ }, 5);
|
|
|
|
|
|
}
|
|
|
|
|
|
- private void createImageReader() {
|
|
|
-
|
|
|
- mImageReader = ImageReader.newInstance(G.WIDTH, G.HEIGHT, PixelFormat.RGBA_8888, 1);
|
|
|
+ private ImageReader createImageReader(DisplayMetrics metric) {
|
|
|
+ if(mImageReader == null) {
|
|
|
+ mImageReader = ImageReader.newInstance(metric.widthPixels, metric.heightPixels, PixelFormat.RGBA_8888, 1);
|
|
|
+ }
|
|
|
+ return mImageReader;
|
|
|
|
|
|
}
|
|
|
|
|
|
public void startVirtual() {
|
|
|
- if (mMediaProjection != null) {
|
|
|
- virtualDisplay();
|
|
|
- } else if (mResultData == null && (mResultData = (Intent) DataUtil.getInstance().getData(REQUEST_CAPTURE_PERMISSION)) == null) {
|
|
|
- G.showToast("请重新点击开始试玩");
|
|
|
+ if (mResultData == null) {
|
|
|
+ floatView.setVisibility(View.VISIBLE);
|
|
|
+ Intent intent = new Intent(getApplicationContext(), MiddleScreenShotAct.class);
|
|
|
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
|
+ startActivity(intent);
|
|
|
+ LogUtil.println("FloatShotScreenService", "没有mResultData");
|
|
|
} else {
|
|
|
- setUpMediaProjection();
|
|
|
virtualDisplay();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void setUpMediaProjection() {
|
|
|
- mMediaProjection = getMediaProjectionManager().getMediaProjection(Activity.RESULT_OK, mResultData);
|
|
|
+ public MediaProjection setUpMediaProjection() {
|
|
|
+ if(mMediaProjection == null) {
|
|
|
+ mMediaProjection = getMediaProjectionManager().getMediaProjection(Activity.RESULT_OK, mResultData);
|
|
|
+ }
|
|
|
+ return mMediaProjection;
|
|
|
}
|
|
|
|
|
|
private MediaProjectionManager getMediaProjectionManager() {
|
|
|
@@ -317,15 +305,20 @@ public class FloatShotScreenService extends Service {
|
|
|
}
|
|
|
|
|
|
private void virtualDisplay() {
|
|
|
- mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
|
|
|
- G.WIDTH, G.HEIGHT, G.DENSITY_DPI, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
|
|
|
- mImageReader.getSurface(), null, null);
|
|
|
- }
|
|
|
+ Display display = windowManager.getDefaultDisplay();
|
|
|
+ DisplayMetrics metric = new DisplayMetrics();
|
|
|
+ display.getMetrics(metric);
|
|
|
|
|
|
- private void startCapture() {
|
|
|
+ mImageReader = createImageReader(metric);
|
|
|
+ mVirtualDisplay = setUpMediaProjection().createVirtualDisplay("screen-mirror",
|
|
|
+ metric.widthPixels, metric.heightPixels, metric.densityDpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
|
|
|
+ mImageReader.getSurface(), null, null);
|
|
|
+ SystemClock.sleep(500);
|
|
|
Image image = mImageReader.acquireLatestImage();
|
|
|
if (image == null) {
|
|
|
- startScreenShot();
|
|
|
+ floatView.setVisibility(View.VISIBLE);
|
|
|
+ G.showToast("请稍候重新截图!");
|
|
|
+ LogUtil.println("FloatShotScreenService", "image");
|
|
|
} else {
|
|
|
Observable.just(image)
|
|
|
.map(new Func1<Image, Bitmap>() {
|
|
|
@@ -341,7 +334,6 @@ public class FloatShotScreenService extends Service {
|
|
|
public void call(Bitmap bitmap) {
|
|
|
//预览图片
|
|
|
if (bitmap != null) {
|
|
|
- DataUtil.getInstance().putData(Bitmap.class.getSimpleName(), bitmap);
|
|
|
new GlobalScreenShot(getApplicationContext()).takeScreenshot(bitmap, new GlobalScreenShot.onScreenShotListener() {
|
|
|
@Override
|
|
|
public void onStartShot() {
|
|
|
@@ -409,6 +401,9 @@ public class FloatShotScreenService extends Service {
|
|
|
|
|
|
private Intent mResultData = null;
|
|
|
|
|
|
+ public void setResultData(Intent mResultData) {
|
|
|
+ this.mResultData = mResultData;
|
|
|
+ }
|
|
|
|
|
|
private ImageReader mImageReader;
|
|
|
|
|
|
@@ -426,4 +421,94 @@ public class FloatShotScreenService extends Service {
|
|
|
mVirtualDisplay.release();
|
|
|
mVirtualDisplay = null;
|
|
|
}
|
|
|
+
|
|
|
+ private class FloatGestureTouchListener extends GestureDetector.SimpleOnGestureListener {
|
|
|
+ int lastX, lastY;
|
|
|
+ int paramX, paramY;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * onDown():刚刚手指接触到触摸屏的那一刹那,就是触的那一下。
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public boolean onDown(MotionEvent event) {
|
|
|
+ lastX = (int) event.getRawX();
|
|
|
+ lastY = (int) event.getRawY();
|
|
|
+ paramX = params.x;
|
|
|
+ paramY = params.y;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * onShowPress():手指按在触摸屏上,它的时间范围:在按下起后,在长按之前
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void onShowPress(MotionEvent e) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * onScroll():手指在屏幕上滑动
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
|
|
|
+ int dx = (int) e2.getRawX() - lastX;
|
|
|
+ int dy = (int) e2.getRawY() - lastY;
|
|
|
+ params.x = paramX + dx;
|
|
|
+ params.y = paramY + dy;
|
|
|
+ // 更新悬浮窗位置
|
|
|
+ windowManager.updateViewLayout(floatView, params);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * onFling():手指在触摸屏上迅速移动,并松开的动作(滑动的比onScroll快)
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * onLongPress():手指在屏幕上停留一段时间 后抬起
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void onLongPress(MotionEvent e) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * onSingleTapUp():手指离开view那一瞬间执行
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public boolean onSingleTapUp(MotionEvent e) {
|
|
|
+ return super.onSingleTapUp(e);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * onSingleTapConfirmed() 同上者,但有附加条件,就是Android会确保单击之后短时间内没有再次单击,才会触发该函数。
|
|
|
+ * 举个列子,如果监听双击事件:onSingleTapUp()会被触发两次。但是onSingleTapConfirmed()一次都不会被触发。
|
|
|
+ * 所以,如果你既想监听单击事件,又想监听双击时间,那么请使用onSingleTapConfirmed()函数。
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public boolean onSingleTapConfirmed(MotionEvent e) {
|
|
|
+ performClick();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通知DoubleTap手势中的事件,包含down、up和move事件(这里指的是在双击之间发生的事件,例如在同一个地方双击会产生DoubleTap手势,而在DoubleTap手势里面还会发生down和up事件,这两个事件由该函数通知);双击的第二下Touch down和up都会触发,可用e.getAction()区分
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public boolean onDoubleTapEvent(MotionEvent e) {
|
|
|
+ return super.onDoubleTapEvent(e);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 在双击的第二下,Touch down时触发
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public boolean onDoubleTap(MotionEvent e) {
|
|
|
+ return super.onDoubleTap(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|