From 1c757c667d4d827cc0bcf692dae663f7ca49b01c Mon Sep 17 00:00:00 2001
From: Runt <qingingrunt2010@qq.com>
Date: Sun, 01 May 2022 08:51:00 +0000
Subject: [PATCH] 悬浮窗  位置移动

---
 app/src/main/java/com/auto/lyric/MainActivity.java                  |   77 ++++++--
 app/src/main/res/values/strings.xml                                 |    1 
 app/src/main/res/layout/float_view.xml                              |   38 +++-
 app/src/main/AndroidManifest.xml                                    |   25 +++
 app/src/main/java/com/auto/lyric/util/DeviceUtil.java               |   18 -
 app/src/main/res/xml/simulateinput.xml                              |   11 +
 app/src/main/java/com/auto/lyric/service/FloatingWindowService.java |  108 +++++++++++++
 app/src/main/java/com/auto/lyric/widgets/Sentence.java              |   25 +++
 app/src/main/res/values/colors.xml                                  |    1 
 app/src/main/java/com/auto/lyric/widgets/LyricView.java             |  151 ++++++++++++++++++
 10 files changed, 412 insertions(+), 43 deletions(-)

diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 63276b4..3d7d703 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -25,6 +25,7 @@
         tools:ignore="ProtectedPermissions" />
     <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+    <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
     <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
     <application
         android:allowBackup="true"
@@ -42,6 +43,30 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+        <service
+            android:name=".service.AutoInputService"
+            android:enabled="true"
+            android:exported="true"
+            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
+            <intent-filter>
+                <action android:name="android.accessibilityservice.AccessibilityService" android:resource="@xml/simulateinput" />
+            </intent-filter>
+            <meta-data
+                android:name="android.accessibilityservice"
+                android:resource="@xml/simulateinput"/>
+        </service>
+        <service
+            android:name=".service.FloatingWindowService"
+            android:enabled="true"
+            android:exported="true"
+            android:permission="android.permission.SYSTEM_OVERLAY_WINDOW|android.permission.SYSTEM_ALERT_WINDOW">
+            <intent-filter>
+                <action android:name="float.service" />
+            </intent-filter>
+            <meta-data
+                android:name="android.accessibilityservice"
+                android:resource="@xml/simulateinput"/>
+        </service>
     </application>
 
 </manifest>
\ No newline at end of file
diff --git a/app/src/main/java/com/auto/lyric/MainActivity.java b/app/src/main/java/com/auto/lyric/MainActivity.java
index 0340eef..462bbc8 100644
--- a/app/src/main/java/com/auto/lyric/MainActivity.java
+++ b/app/src/main/java/com/auto/lyric/MainActivity.java
@@ -1,47 +1,58 @@
 package com.auto.lyric;
 
 import android.content.Intent;
+import android.graphics.PixelFormat;
 import android.net.Uri;
 import android.os.Build;
+import android.os.Handler;
+import android.os.Message;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+
+import androidx.annotation.NonNull;
 
 import com.auto.lyric.base.activities.BaseActivity;
 import com.auto.lyric.databinding.ActivityMainBinding;
+import com.auto.lyric.databinding.FloatViewBinding;
 import com.auto.lyric.service.AutoInputService;
+import com.auto.lyric.service.FloatingWindowService;
 import com.auto.lyric.vm.MainViewModel;
 
 public class MainActivity extends BaseActivity<ActivityMainBinding, MainViewModel> {
 
-    Intent service  = new Intent(getApplicationContext(), AutoInputService.class);
-
     @Override
     public void initViews() {
 
-    }
+        Intent inputService  = new Intent(getApplicationContext(), AutoInputService.class);
 
-    @Override
-    protected void onResume() {
-        super.onResume();
+        Intent floatService  = new Intent(getApplicationContext(), FloatingWindowService.class);
+        binding.button.setOnClickListener(v -> {
 
-        //申请权限
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            //开启悬浮窗
-            if(!Settings.canDrawOverlays(getApplicationContext())) {
-                //启动Activity让用户授权
-                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
-                intent.setData(Uri.parse("package:" + getPackageName()));
-                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
-                startActivity(intent);
-            }else if(!isAccessibilitySettingsOn()){//辅助权限
-                Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
-                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
-                startActivity(intent);
-            }else{//开启监听服务
-                startService(service);
+            //申请权限
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+                //开启悬浮窗
+               /* if(!Settings.canDrawOverlays(getApplicationContext())) {
+                    //启动Activity让用户授权
+                    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
+                    intent.setData(Uri.parse("package:" + getPackageName()));
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
+                    startActivity(intent);
+                }else if(!isAccessibilitySettingsOn()){//辅助权限
+                    Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
+                    startActivity(intent);
+                }else{//开启监听服务
+                    //startService(floatService);
+                }*/
+                startService(floatService);
+                //showFloatView();
             }
-        }
+        });
     }
 
     public boolean isAccessibilitySettingsOn() {
@@ -82,5 +93,27 @@
         return false;
     }
 
+    private void showFloatView(){
+
+
+        //View view = LayoutInflater.from(this).inflate(R.layout.float_view,null);
+        FloatViewBinding binding = FloatViewBinding.inflate(getLayoutInflater());
+        WindowManager manager = (WindowManager) getApplicationContext().getSystemService(WINDOW_SERVICE);
+        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+        }else {
+            params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
+        }
+        params.format = PixelFormat.RGBA_8888;
+        params.gravity = Gravity.CENTER;
+        params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+        params.width = WindowManager.LayoutParams.MATCH_PARENT;
+        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
+        binding.btnBack.setOnClickListener(v ->{
+            stopService(new Intent(this,this.getClass()));
+        });
+        manager.addView(binding.getRoot(),params);
+    }
 
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/auto/lyric/service/FloatingWindowService.java b/app/src/main/java/com/auto/lyric/service/FloatingWindowService.java
new file mode 100644
index 0000000..720e9e6
--- /dev/null
+++ b/app/src/main/java/com/auto/lyric/service/FloatingWindowService.java
@@ -0,0 +1,108 @@
+package com.auto.lyric.service;
+
+import android.app.Service;
+import android.content.Intent;
+import android.graphics.PixelFormat;
+import android.os.Build;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.view.LayoutInflaterFactory;
+
+import com.auto.lyric.R;
+import com.auto.lyric.databinding.FloatViewBinding;
+import com.auto.lyric.util.DeviceUtil;
+
+/**
+ * 全局悬浮窗
+ * Created by Runt (qingingrunt2010@qq.com) on 2022/4/30.
+ */
+public class FloatingWindowService extends Service {
+
+    private WindowManager manager;
+    private WindowManager.LayoutParams params;
+    FloatViewBinding binding;
+    Handler handler;
+    final String TAG = "FloatingWindowService";
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        Log.e(TAG,"onCreate ");
+        View view = LayoutInflater.from(getBaseContext()).inflate(R.layout.float_view,null);
+        binding = FloatViewBinding.bind(view);
+        manager = (WindowManager) getSystemService(WINDOW_SERVICE);
+        params = new WindowManager.LayoutParams();
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+        }else {
+            params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
+        }
+        params.format = PixelFormat.RGBA_8888;
+        params.gravity = Gravity.LEFT | Gravity.TOP;
+        params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+        params.width = WindowManager.LayoutParams.MATCH_PARENT;
+        params.height = DeviceUtil.convertDpToPixel(200,getBaseContext());
+        handler = new Handler(this.getMainLooper()){
+            @Override
+            public void handleMessage(@NonNull Message msg) {
+                binding.lyric.setText(msg.obj.toString());
+                int offset = binding.lyric.getLineCount() * binding.lyric.getLineHeight();
+
+            }
+        };
+        binding.close.setOnClickListener(v ->{
+            stopService(new Intent(this,this.getClass()));
+            stopService(new Intent(this,AutoInputService.class));
+        });
+        binding.floating.setOnTouchListener(new View.OnTouchListener() {
+            int startY;
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                if(event.getAction() == MotionEvent.ACTION_DOWN){
+                    startY = (int) event.getY();
+
+                }else if(event.getAction() == MotionEvent.ACTION_MOVE
+                    || event.getAction() == MotionEvent.ACTION_UP){
+                    params.y = (int) event.getRawY() - DeviceUtil.getStatusBarHeight(getBaseContext()) - startY;
+                    manager.updateViewLayout(binding.getRoot(), params);
+                    Log.e(TAG,"ACTION_MOVE V:"+params.y);
+                }
+                Log.e(TAG,"onTouch event:"+event);
+                Log.e(TAG,"onTouch getRawY:"+event.getRawY());
+                return true;
+            }
+        });
+
+    }
+
+    @Nullable
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        Log.e(TAG,"onStartCommand flags:"+flags+" startId:"+startId+ " intent:"+intent);
+        manager.addView(binding.getRoot(),params);
+        return super.onStartCommand(intent, flags, startId);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        Log.e(TAG,"onDestroy ");
+        manager.removeView(binding.getRoot());
+
+    }
+}
diff --git a/app/src/main/java/com/auto/lyric/util/DeviceUtil.java b/app/src/main/java/com/auto/lyric/util/DeviceUtil.java
index 2e1bdff..b6128a3 100644
--- a/app/src/main/java/com/auto/lyric/util/DeviceUtil.java
+++ b/app/src/main/java/com/auto/lyric/util/DeviceUtil.java
@@ -175,20 +175,12 @@
      * @return
      */
     public static int getStatusBarHeight(Context context) {
-        Class<?> c = null;
-        Object obj = null;
-        Field field = null;
-        int x = 0, statusBarHeight = 0;
-        try {
-            c = Class.forName("com.android.internal.R$dimen");
-            obj = c.newInstance();
-            field = c.getField("status_bar_height");
-            x = Integer.parseInt(field.get(obj).toString());
-            statusBarHeight = context.getResources().getDimensionPixelSize(x);
-        } catch (Exception e1) {
-            e1.printStackTrace();
+        int result = 0;
+        int resId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
+        if (resId > 0) {
+            result = context.getResources().getDimensionPixelOffset(resId);
         }
-        return statusBarHeight;
+        return result;
     }
 
     /**
diff --git a/app/src/main/java/com/auto/lyric/widgets/LyricView.java b/app/src/main/java/com/auto/lyric/widgets/LyricView.java
new file mode 100644
index 0000000..47c4f82
--- /dev/null
+++ b/app/src/main/java/com/auto/lyric/widgets/LyricView.java
@@ -0,0 +1,151 @@
+package com.auto.lyric.widgets;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Typeface;
+import android.media.MediaPlayer;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import com.auto.lyric.R;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 歌词
+ * Created by Runt (qingingrunt2010@qq.com) on 2022/4/30.
+ */
+public class LyricView extends androidx.appcompat.widget.AppCompatTextView {
+    private Paint mPaint;
+    private float mX;
+    private Paint mPathPaint;
+    public int index = 0;
+    private List<Sentence>  list;
+    public float mTouchHistoryY;
+    private int mY;
+    private float middleY;//
+    private static final int DY = 40; //
+    public LyricView(Context context) {
+        super(context);
+        init();
+    }
+    public LyricView(Context context, AttributeSet attr) {
+        super(context, attr);
+        init();
+    }
+    public LyricView(Context context, AttributeSet attr, int i) {
+        super(context, attr, i);
+        init();
+    }
+    private void init() {
+        setFocusable(true);
+        if(list==null){
+            list=new ArrayList<Sentence>();
+            Sentence sen=new Sentence(0," ");
+            list.add(0, sen);
+        }
+        //
+        mPaint = new Paint();
+        mPaint.setAntiAlias(true);
+        mPaint.setTextSize(24);
+        mPaint.setColor(Color.BLACK);
+        mPaint.setAlpha(80);
+        mPaint.setTypeface(Typeface.SERIF);
+        //
+        mPathPaint = new Paint();
+        mPathPaint.setAntiAlias(true);
+        mPathPaint.setColor(Color.RED);
+        mPathPaint.setTextSize(24);
+        mPathPaint.setTypeface(Typeface.SANS_SERIF);
+    }
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        canvas.drawColor(0xEFeffff);
+        Paint p = mPaint;
+        Paint p2 = mPathPaint;
+        p.setTextAlign(Paint.Align.LEFT);
+        if (index == -1)
+            return;
+        p2.setTextAlign(Paint.Align.LEFT);
+        //
+        canvas.drawText(list.get(index).getName(), mX, middleY, p2);
+        float tempY = middleY;
+        //
+        for (int i = index - 1; i  >= 0; i--) {
+            tempY = tempY - DY;
+            if (tempY < 0) {
+                break;
+            }
+            canvas.drawText(list.get(i).getName(), mX, tempY, p);
+        }
+        tempY = middleY;
+        //
+        for (int i = index + 1; i < list.size(); i++) {
+            //
+            tempY = tempY + DY;
+            if (tempY  > mY) {
+                break;
+            }
+            canvas.drawText(list.get(i).getName(), mX, tempY, p);
+        }
+    }
+    protected void onSizeChanged(int w, int h, int ow, int oh) {
+        super.onSizeChanged(w, h, ow, oh);
+        mX = w * 0.3f;
+        mY = h;
+        middleY = h * 0.5f;
+    }
+    public long updateIndex(int index) {
+        if (index == -1)
+            return -1;
+        this.index=index;
+        return index;
+    }
+    public List<Sentence>  getList() {
+        return list;
+    }
+    public void setList(List<Sentence>  list) {
+        this.list = list;
+    }
+    public void updateUI(){
+        new Thread(new updateThread()).start();
+    }
+    class updateThread implements Runnable {
+        long time = 300;
+        int i=0;
+        public void run() {
+            while (true) {
+                long sleeptime = updateIndex(i);
+                time += sleeptime;
+                mHandler.post(mUpdateResults);
+                if (sleeptime == -1)
+                    return;
+                try {
+                    Thread.sleep(time);
+                    i++;
+                    if(i==getList().size())
+                    {
+                        i=0;
+                        time = 300;
+                    }
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+    Handler mHandler = new Handler();
+    Runnable mUpdateResults = new Runnable() {
+        public void run() {
+            invalidate(); //
+        }
+    };
+}
diff --git a/app/src/main/java/com/auto/lyric/widgets/Sentence.java b/app/src/main/java/com/auto/lyric/widgets/Sentence.java
new file mode 100644
index 0000000..f2cdf69
--- /dev/null
+++ b/app/src/main/java/com/auto/lyric/widgets/Sentence.java
@@ -0,0 +1,25 @@
+package com.auto.lyric.widgets;
+
+/**
+ * Created by Runt (qingingrunt2010@qq.com) on 2022/4/30.
+ */
+public class Sentence {
+    private String name;
+    private int index;
+    public Sentence(int index,String name){
+        this.name=name;
+        this.index=index;
+    }
+    public String getName() {
+        return name;
+    }
+    public void setName(String name) {
+        this.name = name;
+    }
+    public int getIndex() {
+        return index;
+    }
+    public void setIndex(int index) {
+        this.index = index;
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/float_view.xml b/app/src/main/res/layout/float_view.xml
index 39a9218..df671b9 100644
--- a/app/src/main/res/layout/float_view.xml
+++ b/app/src/main/res/layout/float_view.xml
@@ -2,45 +2,67 @@
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:background="@color/black_trans"
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
-    <com.google.android.material.floatingactionbutton.FloatingActionButton
+    <ImageButton
         android:id="@+id/floating"
         android:layout_width="40dp"
         android:layout_height="wrap_content"
         android:alpha="0.9"
+        android:src="@android:drawable/ic_notification_overlay"
         app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintLeft_toLeftOf="parent" />
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintBottom_toTopOf="@id/lyric"/>
 
+    <ImageButton
+        android:id="@+id/close"
+        android:layout_width="40dp"
+        android:layout_height="wrap_content"
+        android:alpha="0.9"
+        android:src="@android:drawable/ic_menu_close_clear_cancel"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintBottom_toTopOf="@id/lyric"/>
 
+    <com.auto.lyric.widgets.LyricView
+        android:id="@+id/lyric"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:text="歌词大意"
+        android:gravity="center"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/close"
+        app:layout_constraintBottom_toTopOf="@id/btn_back"/>
 
-    <com.google.android.material.button.MaterialButton
+    <Button
         android:id="@+id/btn_back"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="后退"
         android:textColor="@color/black"
-        android:alpha="0.2"
+        app:layout_constraintTop_toBottomOf="@id/lyric"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintLeft_toLeftOf="parent"/>
 
-    <com.google.android.material.button.MaterialButton
+    <Button
         android:id="@+id/btn_pause"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="暂停"
         android:textColor="@color/black"
-        android:alpha="0.2"
+        app:layout_constraintTop_toBottomOf="@id/lyric"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintLeft_toRightOf="@id/btn_back"
         app:layout_constraintRight_toLeftOf="@id/btn_fast"/>
-    <com.google.android.material.button.MaterialButton
+    <Button
         android:id="@+id/btn_fast"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="快进"
         android:textColor="@color/black"
-        android:alpha="0.2"
+        app:layout_constraintTop_toBottomOf="@id/lyric"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintRight_toRightOf="parent"/>
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 78793ab..bf695cb 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -6,6 +6,7 @@
     <color name="teal_200">#FF03DAC5</color>
     <color name="teal_700">#FF018786</color>
     <color name="black">#FF000000</color>
+    <color name="black_trans">#61000000</color>
     <color name="white">#FFFFFFFF</color>
 
 
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index e5f8fdc..d90fc92 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,2 +1,3 @@
 <resources>
+    <string name="simulate_input_description">simulate_input</string>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/xml/simulateinput.xml b/app/src/main/res/xml/simulateinput.xml
new file mode 100644
index 0000000..7224cff
--- /dev/null
+++ b/app/src/main/res/xml/simulateinput.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<accessibility-service
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:accessibilityEventTypes="typeAllMask"
+    android:accessibilityFeedbackType="feedbackGeneric"
+    android:accessibilityFlags="flagReportViewIds|flagRetrieveInteractiveWindows"
+    android:canRetrieveWindowContent="true"
+    android:description="@string/simulate_input_description"
+    android:packageNames="com.ss.android.ugc.aweme"
+    android:notificationTimeout="1"
+    />
\ No newline at end of file

--
Gitblit v1.9.1