前言
需要编写一个悬浮球应用,抓取qxdm log。
参考文章
Android桌面悬浮窗效果实现,仿360手机卫士悬浮窗效果 Android 悬浮窗、悬浮球开发 Android将Service服务打包jar供三方调用
安卓源码
学习流程
1 环境搭建 2 创建demo,添加按键以及获取窗口参数(长宽) 3 创建服务
3 创建服务
1,2 省略了,已经在如下代码中实现
参考文章: Android Service教程 一个Android Service小例子
MainActivity.java
package com.example.my_application1;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.view.WindowManager;
import android.util.DisplayMetrics;
import android.content.Intent;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private WindowManager mWindowManager;
private Button btn_openfloatball;
private Button btn_closefloatball;
private Button btn_closeapp;
private TextView text;
private TextView text_width;
private TextView text_height;
private int mWidth,mHeight;
private String string_mwidth,string_mheight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initUI();
}
private void start_floatball_service() {
Intent intent_start_floatball_service = new Intent(MainActivity.this, FloatWindowService.class);
startService(intent_start_floatball_service);
}
private void stop_floatball_service() {
Intent intent_stop_floatball_service = new Intent(MainActivity.this, FloatWindowService.class);
stopService(intent_stop_floatball_service);
}
private void initUI() {
btn_openfloatball = findViewById(R.id.openfloatballbtn);
btn_openfloatball.setOnClickListener(new openfloatballListener());
btn_closefloatball = findViewById(R.id.closefloatballbtn);
btn_closefloatball.setOnClickListener(new closefloatballListener());
btn_closeapp = findViewById(R.id.exitbtn);
btn_closeapp.setOnClickListener(new closeappListener());
text = (TextView)findViewById(R.id.textView);
text.setText("init");
mWindowManager = (WindowManager) this.getWindowManager();
DisplayMetrics display = new DisplayMetrics();
mWindowManager.getDefaultDisplay().getMetrics(display);
mWidth = display.widthPixels;
mHeight = display.heightPixels;
text_width = (TextView)findViewById(R.id.WidthText);
text_width.setText("宽度 "+ mWidth);
text_height = (TextView)findViewById(R.id.HeightText);
text_height.setText("高度 "+ mHeight);
}
public class openfloatballListener implements OnClickListener {
@Override
public void onClick(View arg0) {
text = (TextView)findViewById(R.id.textView);
text.setText("button on");
Toast.makeText(getApplicationContext(), "openfloatball", Toast.LENGTH_LONG).show();
start_floatball_service();
}
}
public class closefloatballListener implements OnClickListener {
@Override
public void onClick(View arg0) {
text = (TextView)findViewById(R.id.textView);
text.setText("button off");
stop_floatball_service();
}
}
public class closeappListener implements OnClickListener {
@Override
public void onClick(View arg0) {
android.os.Process.killProcess(android.os.Process.myPid());
}
}
}
FloatWindowService.java
package com.example.my_application1;
import android.app.Service;
import android.widget.Toast;
import android.os.Handler;
import android.os.IBinder;
import android.content.Intent;
public class FloatWindowService extends Service {
private static final String TAG = "FloatWindowService";
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "My Service created", Toast.LENGTH_LONG).show();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "My Service destroy", Toast.LENGTH_LONG).show();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.47"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.61" />
<Button
android:id="@+id/openfloatballbtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="150dp"
android:layout_marginTop="162dp"
android:layout_marginEnd="167dp"
android:text="弹出悬浮窗"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.015" />
<Button
android:id="@+id/closefloatballbtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="150dp"
android:layout_marginEnd="173dp"
android:text="关闭悬浮窗"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.368" />
<Button
android:id="@+id/exitbtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="153dp"
android:layout_marginEnd="170dp"
android:text="关闭app"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.499" />
<TextView
android:id="@+id/WidthText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="52dp"
android:layout_marginLeft="52dp"
android:layout_marginTop="544dp"
android:layout_marginEnd="303dp"
android:layout_marginRight="303dp"
android:layout_marginBottom="168dp"
android:text="窗口宽度"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/HeightText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="51dp"
android:layout_marginTop="22dp"
android:layout_marginEnd="301dp"
android:text="窗口高度"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.333"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.82" />
</androidx.constraintlayout.widget.ConstraintLayout>
androidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.my_application1">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.My_Application1">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".FloatWindowService"
android:enabled="true">
<intent-filter>
<action android:name="com.example.my_application1.FloatWindowService"/>
</intent-filter>
</service>
</application>
</manifest>
自定义服务类基于Service public class Service_name extends Service{} 注意class前不能加abstract,刚开始加了抽象修饰符,导致avd运行app时会闪退。
service创建:创建intent,startService最终调用到自定义的onCreate()。 intent连接各个activity和service 注意调用stopService()。
private void start_floatball_service() {
Intent intent_start_floatball_service = new Intent(MainActivity.this, FloatWindowService.class);
startService(intent_start_floatball_service);
}
用于弹出提示,方便了解当前状态 Toast.makeText(this, “My Service destroy”, Toast.LENGTH_LONG).show();
4 画悬浮球
先了解Activity、Window、View三者关系
注意事项: 1 开显示权限 显示view闪退——未打开上层显示权限 Android: permission denied for window type 2038
2 版本不同,设置的WindowManager.LayoutParams.type不同 悬浮窗权限问题,windowparams.type
3 设置窗口参数
FLAG_NOT_FOCUSABLE和FLAG_NOT_TOUCH_MODAL FLAG_NOT_TOUCH_MODAL——屏幕上弹窗之外的地方能够点击
布局参数 Android布局基础知识:wrap_content,match_parent,layout_weight wrap_content:是layout_width和layout_height的属性值之一,表示和自身内容一样的长度。 match_parent:是layout_width和layout_height的属性值之一,表示和父组件一样的长度。 由于设置悬浮窗口
4 显示view函数差异 //不显示图像,原因待查 mWindowManager.addView(ball,viewparams); 原因:参见mainactivity.java中的set_viewparams(),设置的窗口长宽一开始为FloatWindowSmallView.viewWidth,这两个数值未被定义,所以窗口长宽应该是0.所以不显示。
//重新绘制最上层显示,这个要了解下decorview。 //呈现效果是只显示一个红色的球,其他布局全消失 setContentView(ball);
代码
mainactivity.java
package com.example.demo_v2_addservice;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.view.WindowManager;
import android.util.DisplayMetrics;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
import android.os.IBinder;
import android.content.Intent;
import android.app.Service;
import android.content.Context;
import android.graphics.PixelFormat;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
private static final String TAG_MAIN = "MainActivity";
private WindowManager mWindowManager;
private WindowManager.LayoutParams viewparams;
private Button btn_openfloatball;
private Button btn_closefloatball;
private Button btn_closeapp;
private Button btn_openfloatballview_youkai;
private TextView text;
private TextView text_width;
private TextView text_height;
private int mWidth,mHeight;
private String string_mwidth,string_mheight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
set_viewparams();
initUI();
}
private void set_viewparams() {
if (viewparams == null) {
viewparams = new WindowManager.LayoutParams();
viewparams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
viewparams.format = PixelFormat.RGBA_8888;
viewparams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
viewparams.width = 100;
viewparams.height = 100;
viewparams.gravity = Gravity.LEFT | Gravity.TOP;
viewparams.x = 200;
viewparams.y = 200;
}
}
private void start_floatball_service() {
Intent intent_start_floatball_service = new Intent(MainActivity.this, FloatWindowService.class);
startService(intent_start_floatball_service);
}
private void stop_floatball_service() {
Intent intent_stop_floatball_service = new Intent(MainActivity.this, FloatWindowService.class);
stopService(intent_stop_floatball_service);
}
private void initUI() {
btn_openfloatball = findViewById(R.id.openfloatballbtn);
btn_openfloatball.setOnClickListener(new openfloatballListener());
btn_closefloatball = findViewById(R.id.closefloatballbtn);
btn_closefloatball.setOnClickListener(new closefloatballListener());
btn_closeapp = findViewById(R.id.exitbtn);
btn_closeapp.setOnClickListener(new closeappListener());
btn_openfloatballview_youkai = findViewById(R.id.openfloatballview_youkaibt);
btn_openfloatballview_youkai.setOnClickListener(new openfloatballview_youkaiListener());
text = (TextView)findViewById(R.id.textView);
text.setText("init");
mWindowManager = (WindowManager) this.getWindowManager();
DisplayMetrics display = new DisplayMetrics();
mWindowManager.getDefaultDisplay().getMetrics(display);
mWidth = display.widthPixels;
mHeight = display.heightPixels;
text_width = (TextView)findViewById(R.id.WidthText);
text_width.setText("宽度 "+ mWidth);
text_height = (TextView)findViewById(R.id.HeightText);
text_height.setText("高度 "+ mHeight);
}
public class openfloatballview_youkaiListener implements OnClickListener {
@Override
public void onClick(View arg0) {
text = (TextView)findViewById(R.id.textView);
text.setText("openfloatballview_youkai");
Toast.makeText(getApplicationContext(), "openfloatballview_youkai", Toast.LENGTH_LONG).show();
FloatView_youkai ball = new FloatView_youkai(getApplicationContext());
if(mWindowManager == null){
Toast.makeText(getApplicationContext(), "no wm", Toast.LENGTH_LONG).show();
}
else{
Toast.makeText(getApplicationContext(), "has wm", Toast.LENGTH_LONG).show();
Log.d(TAG_MAIN, "draw ball");
mWindowManager.addView(ball,viewparams);
}
}
}
}
自定义的悬浮球view 移动还未实现。 注意view的长宽,圆心位置,view起始位置。
FloatView_youkai.java
package com.example.demo_v2_addservice;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
public class FloatView_youkai extends View {
private Context mcontext;
Paint paint;
private float cx;
private float cy;
private int radius = 50;
private int screenWidth;
private int screenHeight;
public FloatView_youkai(Context context) {
super(context);
mcontext = context;
paint = new Paint();
paint.setColor(Color.RED);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(20);
screenWidth = 100;
screenHeight = 100;
cx = 50;
cy = 50;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (cx != 0 && cy != 0) {
canvas.drawCircle(cx, cy, radius, paint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
cx = event.getX();
cy = event.getY();
Log.i("----------", "TOUCH");
return super.onTouchEvent(event);
}
}
引入一个问题: 显示圆形后,屏幕除了导航栏都无法触摸。
5 悬浮球增加点击移动功能
WindowManager实现浮动在最顶层视图 关于View的setOnTouchListener和setOnClickListener冲突
1 增加点击view事件监测,及刷新view 预计实现效果:弹出红色悬浮球后,若点击悬浮球,则悬浮球变为绿色,再次点击变回红色。
设置view监听(setOnTouchListener)
public class openfloatballview_youkaiListener implements OnClickListener {
@Override
public void onClick(View arg0) {
text = (TextView)findViewById(R.id.textView);
text.setText("openfloatballview_youkai");
Toast.makeText(getApplicationContext(), "openfloatballview_youkai", Toast.LENGTH_LONG).show();
if(ball == null)
ball = new FloatView_youkai(getApplicationContext());
if(mWindowManager == null){
Toast.makeText(getApplicationContext(), "no wm", Toast.LENGTH_LONG).show();
}
else{
Toast.makeText(getApplicationContext(), "has wm", Toast.LENGTH_LONG).show();
Log.d(TAG_MAIN, "draw ball");
mWindowManager.addView(ball,viewparams);
}
if (ball != null)
{
Toast.makeText(getApplicationContext(), "create ball listener", Toast.LENGTH_LONG).show();
ball.setOnClickListener(new touchfloatballview_youkaiListener());
}
}
}
public class touchfloatballview_youkaiListener implements View.OnClickListener{
@Override
public void onClick(View arg0){
if (mWindowManager != null) {
Toast.makeText(getApplicationContext(), "change ball color", Toast.LENGTH_LONG).show();
ball.paint.setColor(Color.GREEN);
mWindowManager.updateViewLayout(ball, viewparams);
}
}
}
注意:添加touch view监听要放在创建球之后。
监听事件做好了,点击悬浮球会提示改变球的颜色。但未实现。 hhh,先移除ball,再添加就可以了. 在view中有touchevent监听,可以在这里修改球的颜色,但是无法记录当前状态。 可以记录当前值,但是私有数据。 尝试将状态变量定义在main_activity中。
public class MainActivity extends AppCompatActivity {
private boolean ball_status ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWindowManager = (WindowManager) this.getWindowManager();
ball_status = false;
set_viewparams();
initUI();
}
public class touchfloatballview_youkaiListener implements View.OnClickListener{
@Override
public void onClick(View arg0){
if (mWindowManager != null) {
Toast.makeText(getApplicationContext(), "change ball color", Toast.LENGTH_LONG).show();
if(ball_status == false) {
ball.paint.setColor(Color.GREEN);
ball_status = true;
}
else if(ball_status == true) {
ball.paint.setColor(Color.RED);
ball_status = false;
}
else
Log.d("","error value");
mWindowManager.removeView(ball);
mWindowManager.addView(ball, viewparams);
}
}
}
}
需要判断是否已移除view,再在activity的destroy函数中移除view
代码已上传。https://github.com/monsterLang/floatingball/tree/master/demo_v2_addservice
package com.example.demo_v2_addservice;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.view.WindowManager;
import android.util.DisplayMetrics;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
import android.os.IBinder;
import android.content.Intent;
import android.app.Service;
import android.content.Context;
import android.graphics.PixelFormat;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
private static final String TAG_MAIN = "MainActivity";
private WindowManager mWindowManager;
private WindowManager.LayoutParams viewparams;
private FloatView_youkai ball;
private boolean ball_status ;
private boolean ball_status_add ;
private Button btn_openfloatball;
private Button btn_closefloatball;
private Button btn_closeapp;
private Button btn_openfloatballview_youkai;
private Button btn_closefloatballview_youkai;
private TextView text;
private TextView text_width;
private TextView text_height;
private int mWidth,mHeight;
private String string_mwidth,string_mheight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWindowManager = (WindowManager) this.getWindowManager();
ball_status = false;
ball_status_add = false;
set_viewparams();
initUI();
}
private void remove_view() {
mWindowManager.removeView(ball);
ball_status_add = false;
}
private void add_view() {
mWindowManager.addView(ball, viewparams);
ball_status_add = true;
}
private void record_on() {
ball.paint.setColor(Color.GREEN);
ball_status = true;
}
private void record_off() {
ball.paint.setColor(Color.RED);
ball_status = false;
}
private void set_viewparams() {
if (viewparams == null) {
viewparams = new WindowManager.LayoutParams();
viewparams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
viewparams.format = PixelFormat.RGBA_8888;
viewparams.flags =WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
viewparams.width = 100;
viewparams.height = 100;
viewparams.gravity = Gravity.LEFT | Gravity.TOP;
viewparams.x = 200;
viewparams.y = 200;
}
}
private void start_floatball_service() {
Intent intent_start_floatball_service = new Intent(MainActivity.this, FloatWindowService.class);
startService(intent_start_floatball_service);
}
private void stop_floatball_service() {
Intent intent_stop_floatball_service = new Intent(MainActivity.this, FloatWindowService.class);
stopService(intent_stop_floatball_service);
}
private void initUI() {
btn_openfloatball = findViewById(R.id.openfloatballbtn);
btn_openfloatball.setOnClickListener(new openfloatballListener());
btn_closefloatball = findViewById(R.id.closefloatballbtn);
btn_closefloatball.setOnClickListener(new closefloatballListener());
btn_closeapp = findViewById(R.id.exitbtn);
btn_closeapp.setOnClickListener(new closeappListener());
btn_openfloatballview_youkai = findViewById(R.id.openfloatballview_youkaibt);
btn_openfloatballview_youkai.setOnClickListener(new openfloatballview_youkaiListener());
btn_closefloatballview_youkai = findViewById(R.id.closefloatballview_youkaibt);
btn_closefloatballview_youkai.setOnClickListener(new closefloatballview_youkaiListener());
text = (TextView)findViewById(R.id.textView);
text.setText("init");
DisplayMetrics display = new DisplayMetrics();
mWindowManager.getDefaultDisplay().getMetrics(display);
mWidth = display.widthPixels;
mHeight = display.heightPixels;
text_width = (TextView)findViewById(R.id.WidthText);
text_width.setText("宽度 "+ mWidth);
text_height = (TextView)findViewById(R.id.HeightText);
text_height.setText("高度 "+ mHeight);
}
public class openfloatballListener implements OnClickListener {
@Override
public void onClick(View arg0) {
text = (TextView)findViewById(R.id.textView);
text.setText("button on");
Toast.makeText(getApplicationContext(), "openfloatball", Toast.LENGTH_SHORT).show();
start_floatball_service();
}
}
public class closefloatballListener implements OnClickListener {
@Override
public void onClick(View arg0) {
text = (TextView)findViewById(R.id.textView);
text.setText("button off");
stop_floatball_service();
}
}
public class touchfloatballview_youkaiListener implements View.OnClickListener{
@Override
public void onClick(View arg0){
if (mWindowManager != null) {
Toast.makeText(getApplicationContext(), "change ball color", Toast.LENGTH_SHORT).show();
if(ball_status == false) {
record_on();
}
else if(ball_status == true) {
record_off();
}
else
Log.d("","error value");
remove_view();
add_view();
if(ball.getVisibility() == View.VISIBLE)
{
Toast.makeText(getApplicationContext(), "view display", Toast.LENGTH_SHORT).show();
}
}
}
}
public class openfloatballview_youkaiListener implements OnClickListener {
@Override
public void onClick(View arg0) {
text = (TextView)findViewById(R.id.textView);
text.setText("openfloatballview_youkai");
Toast.makeText(getApplicationContext(), "openfloatballview_youkai", Toast.LENGTH_SHORT).show();
if(ball == null)
ball = new FloatView_youkai(getApplicationContext());
if(mWindowManager == null){
Toast.makeText(getApplicationContext(), "no wm", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getApplicationContext(), "has wm", Toast.LENGTH_SHORT).show();
Log.d(TAG_MAIN, "draw ball");
if(ball_status_add == false) {
add_view();
}
}
if (ball != null)
{
Toast.makeText(getApplicationContext(), "create ball listener", Toast.LENGTH_SHORT).show();
ball.setOnClickListener(new touchfloatballview_youkaiListener());
}
}
}
public class closefloatballview_youkaiListener implements OnClickListener {
@Override
public void onClick(View arg0) {
text = (TextView)findViewById(R.id.textView);
text.setText("closefloatballview_youkai");
Toast.makeText(getApplicationContext(), "closefloatballview_youkai", Toast.LENGTH_SHORT).show();
if(mWindowManager == null){
Toast.makeText(getApplicationContext(), "no wm", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getApplicationContext(), "has wm", Toast.LENGTH_SHORT).show();
Log.d(TAG_MAIN, "draw ball");
if(ball_status_add == true)
{
remove_view();
if(ball_status == true) {
record_off();
}
}
}
}
}
public class closeappListener implements OnClickListener {
@Override
public void onClick(View arg0) {
if(ball.getVisibility() == View.VISIBLE)
mWindowManager.removeView(ball);
android.os.Process.killProcess(android.os.Process.myPid());
}
}
}
package com.example.demo_v2_addservice;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
public class FloatView_youkai extends View {
private Context mcontext;
private FloatView_youkai view;
private boolean status_ball;
Paint paint;
private float cx;
private float cy;
private int radius = 50;
private int screenWidth;
private int screenHeight;
private void setOnTouchListener() {
if (view != null)
{
view.setOnTouchListener(new View.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event) {
paint.setColor(Color.GREEN);
Log.d("----------", "TOUCH");
return true;
}
});
}
}
public FloatView_youkai(Context context) {
super(context);
mcontext = context;
paint = new Paint();
paint.setColor(Color.RED);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(20);
screenWidth = 100;
screenHeight = 100;
cx = 50;
cy = 50;
view = this;
status_ball = false;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (cx != 0 && cy != 0) {
canvas.drawCircle(cx, cy, radius, paint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i("----------", "TOUCH");
return super.onTouchEvent(event);
}
}
2 增加移动事件监测 需要修改圆心位置 点击和移动事件区分开
待办
添加log
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private static final String TAG_MAIN = "MainActivity";
}
Log.d(TAG_MAIN, "draw ball");
报错
Hardcoded string “floatball”, should use @string resource Hardcoded string 汉字, should use @string resource警告
参照文章
使用WindowManager添加View——悬浮窗口的基本原理 - cpacm - 博客园 WindowManager addView弹窗功能_feiyangxiaomi的专栏-CSDN博客 WindowManager实现浮动在最顶层视图 - 程序员大本营 WindowManager实现浮动在最顶层视图_搬砖路上的博客-CSDN博客 view 的绘制和刷新_luyuqin0115的博客-CSDN博客_view刷新 android onTouchEvent和setOnTouchListener中onTouch的区别 - 淡泊名利 - 博客园 理解Window和WindowManager(一)window的添加删除更新view_dev晴天的博客-CSDN博客 Android事件分发、View事件Listener全解析_学无常师,负笈不远险阻-CSDN博客 View的setOnClickListener的添加方法_小宇宙的小怪兽-CSDN博客 请教关于 View.OnClickListener() 的问题_rongliu1741的博客-CSDN博客 Android 源码解析之WindowManager更新窗口_小王君的专栏-CSDN博客 Cross Reference: /frameworks/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java
|