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