x1ongzhu преди 6 години
родител
ревизия
d444c17df0

+ 1 - 0
android/app/src/main/AndroidManifest.xml

@@ -10,6 +10,7 @@
         android:name="com.izouma.screen_stream_plugin.MyApplication"
         android:icon="@mipmap/ic_launcher"
         android:label="猿人电竞"
+        android:networkSecurityConfig="@xml/network_security_config"
         android:usesCleartextTraffic="true">
         <activity
             android:name="com.yalantis.ucrop.UCropActivity"

+ 8 - 0
android/app/src/main/res/xml/network_security_config.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+    <base-config cleartextTrafficPermitted="true">
+        <trust-anchors>
+            <certificates src="system" />
+        </trust-anchors>
+    </base-config>
+</network-security-config>

+ 9 - 2
screen_stream_plugin/android/src/main/AndroidManifest.xml

@@ -1,3 +1,10 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.izouma.screen_stream_plugin">
-    <application><service android:name=".VideoProcessService" android:enabled="true" android:exported="true"></service></application>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.izouma.screen_stream_plugin">
+
+    <application android:usesCleartextTraffic="true">
+        <service
+            android:name=".VideoProcessService"
+            android:enabled="true"
+            android:exported="true"></service>
+    </application>
 </manifest>

+ 86 - 23
screen_stream_plugin/android/src/main/java/com/izouma/screen_stream_plugin/ScreenStreamPlugin.java

@@ -2,13 +2,17 @@ package com.izouma.screen_stream_plugin;
 
 import android.annotation.TargetApi;
 import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
 import android.graphics.Color;
 import android.graphics.PixelFormat;
 import android.media.projection.MediaProjectionManager;
@@ -16,16 +20,23 @@ import android.net.Uri;
 import android.os.Build;
 import android.os.IBinder;
 import android.provider.Settings;
+import android.util.TypedValue;
 import android.view.Gravity;
+import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.WindowManager;
 import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.TextView;
 
 import org.json.JSONException;
 import org.json.JSONObject;
 
 import java.util.Objects;
+import java.util.Timer;
+import java.util.TimerTask;
 
 import io.flutter.plugin.common.MethodCall;
 import io.flutter.plugin.common.MethodChannel;
@@ -47,7 +58,7 @@ public class ScreenStreamPlugin implements MethodChannel.MethodCallHandler, Plug
 
     private WindowManager              windowManager;
     private WindowManager.LayoutParams layoutParams;
-    private Button                     floatButton;
+    private ImageButton                floatButton;
     private int                        playerInfoId;
 
     private VideoProcessService.VideoProcessBinder videoProcessBinder;
@@ -86,10 +97,12 @@ public class ScreenStreamPlugin implements MethodChannel.MethodCallHandler, Plug
         layoutParams.format = PixelFormat.RGBA_8888;
         layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
         layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-        layoutParams.width = 200;
-        layoutParams.height = 100;
-        layoutParams.x = 300;
-        layoutParams.y = 300;
+        layoutParams.width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 42, registrar.activity().getResources().getDisplayMetrics());
+        layoutParams.height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, registrar.activity().getResources().getDisplayMetrics());
+        layoutParams.x = layoutParams.width / 2;
+        layoutParams.y = layoutParams.height / 2;
+
+        // showFloatWindow();
     }
 
     @Override
@@ -149,22 +162,27 @@ public class ScreenStreamPlugin implements MethodChannel.MethodCallHandler, Plug
         if (floatButton != null) {
             return;
         }
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//判断系统版本
-            if (Settings.canDrawOverlays(registrar.context())) {
-                floatButton = new Button(registrar.context().getApplicationContext());
-                floatButton.setText("CLICK ME!");
-                floatButton.setBackgroundColor(Color.LTGRAY);
-                floatButton.setVisibility(View.GONE);
-                windowManager.addView(floatButton, layoutParams);
-                floatButton.setOnTouchListener(new FloatingOnTouchListener());
-            }
-        } else {
-            floatButton = new Button(registrar.context().getApplicationContext());
-            floatButton.setText("CLICK ME!");
-            floatButton.setBackgroundColor(Color.LTGRAY);
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(registrar.context())) {
+            floatButton = new ImageButton(registrar.context().getApplicationContext());
+            floatButton.setAlpha(0.5f);
+            floatButton.setPadding(0, 0, 0, 0);
+            floatButton.setScaleType(ImageView.ScaleType.CENTER_CROP);
+            floatButton.setImageResource(R.mipmap.icon_float_button);
+            floatButton.setBackgroundColor(Color.TRANSPARENT);
             floatButton.setVisibility(View.GONE);
             windowManager.addView(floatButton, layoutParams);
             floatButton.setOnTouchListener(new FloatingOnTouchListener());
+            floatButton.setOnClickListener(v -> {
+                floatButton.setEnabled(false);
+                Timer timer = new Timer();
+                timer.schedule(new TimerTask() {
+                    @Override
+                    public void run() {
+                        registrar.activity().runOnUiThread(() -> floatButton.setEnabled(true));
+                    }
+                }, 500);
+                showCustomPopupMenu();
+            });
         }
     }
 
@@ -240,6 +258,7 @@ public class ScreenStreamPlugin implements MethodChannel.MethodCallHandler, Plug
         public boolean onTouch(View view, MotionEvent event) {
             switch (event.getAction()) {
                 case MotionEvent.ACTION_DOWN:
+                    floatButton.setAlpha(1f);
                     x = (int) event.getRawX();
                     y = (int) event.getRawY();
                     ts = System.currentTimeMillis();
@@ -258,11 +277,7 @@ public class ScreenStreamPlugin implements MethodChannel.MethodCallHandler, Plug
                     moved = true;
                     break;
                 case MotionEvent.ACTION_UP:
-                    if (System.currentTimeMillis() - ts < 300) {
-                        Intent intent = new Intent(registrar.context().getApplicationContext(), registrar.activity().getClass());
-                        intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
-                        registrar.activity().startActivity(intent);
-                    }
+                    makeTranslucent();
                     break;
                 default:
                     break;
@@ -270,4 +285,52 @@ public class ScreenStreamPlugin implements MethodChannel.MethodCallHandler, Plug
             return false;
         }
     }
+
+    public static String getApplicationName(Context context) {
+        ApplicationInfo applicationInfo = context.getApplicationInfo();
+        int stringId = applicationInfo.labelRes;
+        return stringId == 0 ? applicationInfo.nonLocalizedLabel.toString() : context.getString(stringId);
+    }
+
+    private void showCustomPopupMenu() {
+        LayoutInflater layoutInflater = (LayoutInflater) this.registrar.context().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        View dialogOverlay = layoutInflater.inflate(R.layout.dialog, null);
+        dialogOverlay.findViewById(R.id.btn_cancel).setOnClickListener(v -> {
+            windowManager.removeView(dialogOverlay);
+        });
+        dialogOverlay.findViewById(R.id.btn_ok).setOnClickListener(v -> {
+            windowManager.removeView(dialogOverlay);
+            Intent intent = new Intent(registrar.context().getApplicationContext(), registrar.activity().getClass());
+            intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
+            registrar.activity().startActivity(intent);
+        });
+
+        ((TextView) dialogOverlay.findViewById(R.id.tv_msg)).setText("是否立即返回" + getApplicationName(registrar.context()) + "?");
+        WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+        } else {
+            params.type = WindowManager.LayoutParams.TYPE_PHONE;
+        }
+        params.format = PixelFormat.RGBA_8888;
+        params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+        params.gravity = Gravity.CENTER;
+        windowManager.addView(dialogOverlay, params);
+    }
+
+    private Timer timer;
+
+    private void makeTranslucent() {
+        if (timer != null) {
+            timer.cancel();
+        }
+        timer = new Timer();
+        timer.schedule(new TimerTask() {
+            @Override
+            public void run() {
+                registrar.activity().runOnUiThread(() -> floatButton.setAlpha(0.5f));
+                timer = null;
+            }
+        }, 2000);
+    }
 }

+ 32 - 7
screen_stream_plugin/android/src/main/java/com/izouma/screen_stream_plugin/VideoProcessService.java

@@ -25,7 +25,10 @@ import android.os.SystemClock;
 import android.text.format.DateUtils;
 
 import net.gotev.uploadservice.MultipartUploadRequest;
+import net.gotev.uploadservice.ServerResponse;
+import net.gotev.uploadservice.UploadInfo;
 import net.gotev.uploadservice.UploadNotificationConfig;
+import net.gotev.uploadservice.UploadStatusDelegate;
 
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -40,12 +43,12 @@ import static net.gotev.uploadservice.Placeholders.UPLOADED_FILES;
 import static net.gotev.uploadservice.Placeholders.UPLOAD_RATE;
 
 public class VideoProcessService extends Service implements ImageAvailableListener.OnMatchedListener {
-    private static final String TAG          = "VideoProcessService";
-    private static final int    MSG_START    = 0x111;
-    private static final int    MSG_STOP     = 0x112;
-    private static final int    NOTIFY_ID    = 0x1fff;
-    private static final String CHANNEL_ID   = "Recording";
-    private static final String CHANNEL_NAME = "Screen Recorder Notifications";
+    private static final String TAG             = "VideoProcessService";
+    private static final int    MSG_START       = 0x111;
+    private static final int    MSG_STOP        = 0x112;
+    private static final String CHANNEL_ID      = "Recording";
+    private static final String CHANNEL_NAME    = "Screen Recorder Notifications";
+    private final static int    NOTIFICATION_ID = android.os.Process.myPid();
 
     private int                    playerInfoId;
     private MediaProjection        mediaProjection;
@@ -67,6 +70,7 @@ public class VideoProcessService extends Service implements ImageAvailableListen
         if (Build.VERSION.SDK_INT >= O) {
             createNotificationChannel();
         }
+        startForeground(NOTIFICATION_ID, getBuilder().build());
         new Thread() {
             @Override
             public void run() {
@@ -106,6 +110,27 @@ public class VideoProcessService extends Service implements ImageAvailableListen
                                     .addParameter("id", String.valueOf(playerInfoId))
                                     .setNotificationConfig(getNotificationConfig())
                                     .setMaxRetries(3)
+                                    .setDelegate(new UploadStatusDelegate() {
+                                        @Override
+                                        public void onProgress(Context context, UploadInfo uploadInfo) {
+
+                                        }
+
+                                        @Override
+                                        public void onError(Context context, UploadInfo uploadInfo, ServerResponse serverResponse, Exception exception) {
+                                            System.out.println("upload error");
+                                        }
+
+                                        @Override
+                                        public void onCompleted(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) {
+
+                                        }
+
+                                        @Override
+                                        public void onCancelled(Context context, UploadInfo uploadInfo) {
+
+                                        }
+                                    })
                                     .startUpload();
                         } catch (Exception e) {
                             e.printStackTrace();
@@ -186,7 +211,7 @@ public class VideoProcessService extends Service implements ImageAvailableListen
         Notification notification = getBuilder()
                 .setContentText("已录制: " + DateUtils.formatElapsedTime(timeMs / 1000))
                 .build();
-        getNotificationManager().notify(NOTIFY_ID, notification);
+        getNotificationManager().notify(NOTIFICATION_ID, notification);
         mLastFiredTime = SystemClock.elapsedRealtime();
     }
 

+ 7 - 0
screen_stream_plugin/android/src/main/res/drawable/bg_dialog.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="#FF15151D" />
+    <stroke
+        android:width="1dp"
+        android:color="#FFC2524D" />
+</shape>

+ 65 - 0
screen_stream_plugin/android/src/main/res/layout/dialog.xml

@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:background="#00000000"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="270dp"
+        android:layout_height="206dp"
+        android:layout_centerInParent="true"
+        android:background="@drawable/bg_dialog"
+        android:gravity="center|top"
+        android:orientation="vertical">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:layout_marginTop="25dp"
+            android:text="提醒"
+            android:textColor="@android:color/white"
+            android:textSize="18sp"
+            android:textStyle="bold" />
+
+        <TextView
+            android:id="@+id/tv_msg"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="20dp"
+            android:text="是否立即返回猿人电竞APP"
+            android:textColor="@android:color/white" />
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="50dp">
+
+            <Button
+                android:id="@+id/btn_cancel"
+                style="@style/Widget.AppCompat.Button.Borderless"
+                android:layout_width="100dp"
+                android:layout_height="36dp"
+                android:background="#FF3A3D5C"
+                android:padding="0dp"
+                android:text="取消"
+                android:textColor="@android:color/white"
+                android:textSize="14sp"
+                android:textStyle="bold" />
+
+            <Button
+                android:id="@+id/btn_ok"
+                style="@style/Widget.AppCompat.Button.Borderless"
+                android:layout_width="100dp"
+                android:layout_height="36dp"
+                android:layout_marginLeft="20dp"
+                android:background="#FFC2524D"
+                android:padding="0dp"
+                android:text="确认"
+                android:textColor="@android:color/white"
+                android:textSize="14sp"
+                android:textStyle="bold" />
+        </LinearLayout>
+    </LinearLayout>
+</RelativeLayout>

BIN
screen_stream_plugin/android/src/main/res/mipmap-xhdpi/icon_float_button.png


BIN
screen_stream_plugin/android/src/main/res/mipmap-xxhdpi/icon_float_button.png


BIN
screen_stream_plugin/android/src/main/res/mipmap-xxxhdpi/icon_float_button.png