Android浮动小球与开机自启动

  看着手机上的360浮动小球,不评价其具体的功能与实用性,至少在UI设计与交互方面是个不小的创新。

  

  如图片左上角所示,球中还会显示当前手机的运行状况,向下拉动还会有弹射来达到加速、清理等目的。

  那好,先来实现一个类似的小球(仅限于形状,功能你懂得)。

  查阅了相关资料,整个界面除了小球以外,其他部分均是做透明处理。

  1、由于用到了CompatModeWrapper,所以需要在AndroidManifest.xml中添加以下权限:

1 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

  要想在应用中被启动为一个Activity或Service,需要注册,这里是Service:

1 <service android:name=".Service1" />

  2、界面透明化处理,整体代码如下:

  1 package com.XXX.autostart;
  2 
  3 import android.view.View;
  4 
  5 import android.app.Service;
  6 import android.content.Intent;
  7 import android.graphics.PixelFormat;
  8 import android.os.Handler;
  9 import android.os.IBinder;
 10 import android.view.Gravity;
 11 import android.view.LayoutInflater;
 12 import android.view.MotionEvent;
 13 import android.view.WindowManager;
 14 import android.view.View.OnClickListener;
 15 import android.view.View.OnTouchListener;
 16 import android.view.WindowManager.LayoutParams;
 17 import android.widget.ImageButton;
 18 import android.widget.LinearLayout;
 19 
 20 public class Service1 extends Service
 21 {
 22     LinearLayout mFloatLayout;
 23     WindowManager.LayoutParams wmParams;
 24     WindowManager mWindowManager;
 25 
 26     ImageButton mFloatView;
 27 
 28     @Override
 29     public void onCreate()
 30     {
 31         // TODO Auto-generated method stub
 32         super.onCreate();
 33 
 34         createFloatView();
 35     }
 36 
 37     @Override
 38     public IBinder onBind(Intent intent)
 39     {
 40         // TODO Auto-generated method stub
 41         return null;
 42     }
 43 
 44     private void createFloatView()
 45     {
 46         wmParams = new WindowManager.LayoutParams();
 47 
 48         mWindowManager = (WindowManager)getApplication().getSystemService(getApplication().WINDOW_SERVICE);
 49 
 50         wmParams.type = LayoutParams.TYPE_PHONE;
 51         wmParams.format = PixelFormat.RGBA_8888;
 52 
 53         wmParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE;
 54 
 55         wmParams.gravity = Gravity.LEFT | Gravity.TOP;
 56 
 57         wmParams.x = 0;
 58         wmParams.y = 0;
 59 
 60         wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
 61         wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
 62 
 63         LayoutInflater inflater = LayoutInflater.from(getApplication());
 64         mFloatLayout = (LinearLayout) inflater.inflate(R.layout.float_layout, null);
 65 
 66     mWindowManager.addView(mFloatLayout, wmParams);
 67 
 68         mFloatView = (ImageButton)mFloatLayout.findViewById(R.id.float_id);
 69 
 70         mFloatLayout.measure(View.MeasureSpec.makeMeasureSpec(0,
 71         View.MeasureSpec.UNSPECIFIED), View.MeasureSpec
 72                 .makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
 73 
 74 
 75         mFloatView.setOnTouchListener(new OnTouchListener() {
 76             @Override
 77             public boolean onTouch(View v, MotionEvent event) {
 78                 // TODO Auto-generated method stub
 79 
 80                 wmParams.x = (int) event.getRawX() - mFloatView.getMeasuredWidth() / 2;
 81 
 82                 wmParams.y = (int) event.getRawY() - mFloatView.getMeasuredHeight() / 2 - 25;
 83 
 84         mWindowManager.updateViewLayout(mFloatLayout, wmParams);
 85                 return false;
 86             }
 87         });
 88 
 89         mFloatView.setOnClickListener(new OnClickListener() {
 90 
 91             @Override
 92             public void onClick(View v) {
 93                 // TODO Auto-generated method stub
 94                 mFloatView.setVisibility(View.INVISIBLE);
 95 
 96                 Handler handler = new Handler();
 97                 handler.postDelayed(new Runnable() {
 98                     public void run() {
 99                         mFloatView.setVisibility(View.VISIBLE);
100                     }
101                 }, 3000);
102 
103             }
104         });
105     }
106 
107     @Override
108     public void onDestroy()
109     {
110         // TODO Auto-generated method stub
111         super.onDestroy();
112         if(mFloatLayout != null)
113         {
114             mWindowManager.removeView(mFloatLayout);
115         }
116     }
117 
118 }

  这里是利用ImageButton组件来实现小球,关键在于其显示的图片是圆形。

  因此,要想将浮动窗口实现为其他形状,只需制作相应的图片赋给组件。

  对于小球的功能,只是实现了在手机屏幕上随意拖动,单击消失三秒后重现。

  3、浮动小球有了,怎么让它启动呢?注意上面实现的类Service1,继承的是Service。

  在ManiActivity.java中,让其显现的方式很简单,代码如下:

1 finish();
2 Intent intent = new Intent(getApplicationContext(), Service1.class);
3 startService(intent);

  注意,这里对于MainActivity类不需要做任何处理,新建工程时默认就好。当然,要实现其他功能例外。

  代码finish();可加可不加,加上之后使得程序一运行就只剩下小球,原来的界面让其消失。

  效果图如下,图形找的是红色小火焰。

      

  4、到此,浮动小球就实现了,那怎么让它开机自启动呢?

  其实也很简单,用到了BroadcastReceiver。

  还是先添加权限:

1 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

  另外,对于系统的广播消息,要想在开机等时刻能够捕获到,还需添加以下内容:

1 <receiver android:name=".BootBroadcastReceiver">
2         <intent-filter>
3                 <action android:name="android.intent.action.BOOT_COMPLETED" />
4         </intent-filter>
5 </receiver>

  实现代码如下:

 1 package com.XXX.autostart;
 2 
 3 import android.content.BroadcastReceiver;
 4 import android.content.Context;
 5 import android.content.Intent;
 6 
 7 public class BootBroadcastReceiver extends BroadcastReceiver {
 8 
 9     static final String ACTION = "android.intent.action.BOOT_COMPLETED";
10 
11     @Override
12     public void onReceive(Context context, Intent intent) {
13 
14         if (intent.getAction().equals(ACTION)) {
15             Intent intent1 = new Intent(context, Service1.class);
16             intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
17             context.startService(intent1);
18         }
19     }
20 }

  

  将手机ReBoot,可以发现红色小球会自行启动,不过速度比较慢(和360安全卫士相比)。

原文地址:https://www.cnblogs.com/tgyf/p/4665401.html