这个项目是从网上找的,自己分析了下。
<a target=_blank href="http://download.csdn.net/detail/jonemill/8274695">360安仔,点击打开,不行就复制下下载地址</a>
<a target=_blank href="http://download.csdn.net/detail/jonemill/8274695">360安仔下载地址点击打开链接</a>
package com.malinkang.AssistAnZai;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
//设置界面
/**
* 1.刚开启应用,就通过activity开启一项服务。再服务里代码注册广播(目的为了在程序结束的时候可以杀死广播),sendBroadcast发送广播事件。
广播事件一直在后台运行,直到如果接受到的是桌面,就创建安仔。这是其一。
2.在开启应用的时候,通过判断cb,如果打对勾,就在移除安仔。
*
* @author Administrator
*
*/
public class SettingActivity extends Activity {
private SharedPreferences sp;
private Editor editor;
private Intent intent;
private AnZaiApplication application;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//得到应用程序上下文
application = (AnZaiApplication) getApplicationContext();
//得到sharedpreferance
sp = getSharedPreferences("config", Context.MODE_PRIVATE);
editor = sp.edit();
CheckBox cb = (CheckBox) findViewById(R.id.cb);
//得到sp中的值,默认为false
boolean displayOnlyOnHome = sp.getBoolean("displayOnlyOnHome", false);
//checkbox默认不开启
cb.setChecked(displayOnlyOnHome);
//如果checkbox选中,就从application中移除view。 2个判断,这是第一个。一开始就判断
if (displayOnlyOnHome) {
//此时就只在着桌面显示。
application.removeView();
//此时在桌面和程序中显示。
} else {
application.createView();
}
//给cb设置监听时事件
cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
//向通过editor向sp中放入数据
editor.putBoolean("displayOnlyOnHome", isChecked);
editor.commit();
//这是第二个判断
if (isChecked) {
//桌面显示
application.removeView();
} else {
//桌面和程序中显示。
application.createView();
}
}
});
//开启service。显示地开启
intent = new Intent(this, FloatingService.class);
startService(intent);
}
}
package com.malinkang.AssistAnZai;
import java.util.ArrayList;
import java.util.List;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.AsyncTask;
import android.os.IBinder;
/**
* 开启一项服务。发送广播 。如果收到的在window桌面显示的广播,就在桌面显示。
* 刚开启应用就开启一项服务,如果接受的广播是在手机的桌面,就创建一个小安仔。
* 若果接受的广播不在手机桌面,就不创建。
* @author Administrator
*
*/
public class FloatingService extends Service {
private SharedPreferences sp;
private FloatingService service;
private InnerReceiver receiver;
private AnZaiApplication application;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
//
super.onCreate();
service=this;
//实例化广播事件broadcastRecevier
receiver = new InnerReceiver();
sp=getSharedPreferences("config", Context.MODE_PRIVATE);
IntentFilter filter = new IntentFilter();
application = (AnZaiApplication) getApplicationContext();
//添加动作
filter.addAction("com.malinkang.action.IsHome");
filter.addAction("com.malinkang.action.NotHome");
//注册接受者 通过代码注册广播。也可以通过在配置文件中添加。
registerReceiver(receiver, filter);
//开启一个子线程发送广播。
new AsyncTask<Void, Void, Void>() {
//这个方法在doinbackgroud中调用。
private void send(boolean isHome){
//在此项服务中发送广播
if(isHome) {
//仅在桌面显示
service.sendBroadcast(new Intent("com.malinkang.action.IsHome"));
System.out.println("zhuomian");
} else {
service .sendBroadcast(new Intent("com.malinkang.action.NotHome"));
System.out.println("bushizhuomian");
}
}
@Override
protected Void doInBackground(Void... params) {
//默认不在桌面
boolean oldIsHome = false;
//永真循环
while(true){
boolean isHome=isHome();
//如果在桌面
if(oldIsHome != isHome) {
send(isHome);
oldIsHome = isHome;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.execute();
}
//初始化浮动窗体
//广播接受者 //接受到广播事件然后在onreceiver中处理
private class InnerReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//如果接受到的广播是sp.getBoolean是假,就什么都不做。
if(!sp.getBoolean("displayOnlyOnHome", false)){
System.out.println(sp.getBoolean("displayOnlyOnHome", false));
return;
}
String action = intent.getAction();
//如果接受到广播是在桌面就创建
if("com.malinkang.action.IsHome".equals(action)){
//在桌面window创建view
application.createView();
System.out.println("是桌面");
}else if("com.malinkang.action.NotHome".equals(action)) {
application.removeView();
System.out.println("不是桌面");
}
}
}
//判断是否是桌面 如果是桌面的话就代表,所有activity的包名包含着运行中任务栈最顶端的activity的包名
public boolean isHome(){
//获取所有桌面的Activity的包名
List<String> homes=getHomes();
//得到活动管理者。
ActivityManager mActivityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
//在getRunningTasks()所返回的Task队列中系统会根据这些Task的活跃度有一个排序,越活跃越是靠前。第一个就是当前活动的Task
List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(Integer.MAX_VALUE);
//其中runningTaskInfos 的 topActivity就是当前Task的活跃Activity
return homes.contains(rti.get(0).topActivity.getPackageName());
}
//获取所有桌面的Activity的包名
private List<String> getHomes() {
//创建一个arraylist集合。
List<String> packages = new ArrayList<String>();
//得到包管理器。
PackageManager packageManager = getPackageManager();
//新建intent 添加action和category
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
//表示list中只能存放ResolveInfo(这是类)类型的对象。 resolveInfo是个集合。
//返回给定条件的所有ResolveInfo对象(本质上是Activity),集合对象
//根据<intent>节点来获取其上一层目录的信息,通常是<activity>、<receiver>、<service>节点信息
List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
//(类型 对象:集合)
for(ResolveInfo info : resolveInfo){
//获取对象中的包名放入另外一个list集合中。
packages.add(info.activityInfo.packageName);
}
return packages;
}
//在destory方法中反注册。
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
}
package com.malinkang.AssistAnZai;
import java.util.ArrayList;
import java.util.List;
import android.app.ActivityManager;
import android.app.ActivityManager.RecentTaskInfo;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.os.Vibrator;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
//该悬浮窗口是不隶属于Activity界面的,也就是说,他是隶属于启动它的应用程序所在进程
//应用程序的上下文
public class AnZaiApplication extends Application {
private WindowManager wm;
private LayoutParams params;
private ImageView iv_anzai;
private View view;
private Editor editor;
private SharedPreferences sp;
private boolean isRight;
private boolean isMove;
private boolean anzaiIsDisplay;// 安仔是否显示
private MyOnClickListener mOnClickListener;
@Override
public void onCreate() {
initAnZai();
super.onCreate();
}
/**
* 初始化安仔窗体 默认的 不管点击与否,都在window桌面显示 。
*/
private void initAnZai() {
sp = getSharedPreferences("config", Context.MODE_PRIVATE);
editor = sp.edit();
wm = (WindowManager) getSystemService("window");
//wm的参数。
params = new LayoutParams();
//view控件 这个view要挂在wm上。
view = View.inflate(this, R.layout.assist_anzai, null);
// 为view注册触摸事件
view.setOnTouchListener(new MyOnTouchListener());
//子控件
iv_anzai = (ImageView) view.findViewById(R.id.anzai_icon);
// 判断是否在右边 设置 图片显示,默认在右边
isRight = sp.getBoolean("isRight", false);
if (isRight) {
iv_anzai.setImageResource(R.drawable.assist_anzai_right_green);
} else {
iv_anzai.setImageResource(R.drawable.assist_anzai_left_green);
}
//布局参数的类型 格式 标示 xy 高度宽度 gravity
params.type = LayoutParams.TYPE_PHONE;
params.format = PixelFormat.RGBA_8888;
params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_NOT_FOCUSABLE;
params.x = (int) sp.getFloat("x", 0);
params.y = (int) sp.getFloat("y", 0);
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
//左上角
params.gravity = Gravity.LEFT | Gravity.TOP;
mOnClickListener = new MyOnClickListener();
}
// 显示安仔 再程序app中添加安仔
public void createView() {
if (anzaiIsDisplay)
return;
//显示安仔 向wm中添加view,参数为params。
wm.addView(view, params);
anzaiIsDisplay = true;
}
// 移除安仔
public void removeView() {
if (!anzaiIsDisplay)
return;
wm.removeView(view);
anzaiIsDisplay = false;
}
/**
* 安仔触摸监听器
*
* @author malinkang
*
*/
private class MyOnTouchListener implements OnTouchListener {
int startx;
int starty;
public boolean onTouch(View v, MotionEvent event) {
//得到屏幕的宽度
int screenWidth = getResources().getDisplayMetrics().widthPixels;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 获取按下的时候相对于Activity左上角的坐标
startx = (int) event.getRawX();
starty = (int) event.getRawY();
if (isRight) {
iv_anzai.setImageResource(R.drawable.assist_anzai_pressed_right_green);
} else {
iv_anzai.setImageResource(R.drawable.assist_anzai_pressed_left_green);
}
break;
case MotionEvent.ACTION_MOVE:
int newx = (int) event.getRawX();
int newy = (int) event.getRawY();
if (newx > 35 && (screenWidth - newx) > 35) {
isMove = true;
iv_anzai.setImageResource(R.drawable.assist_anzai_middle_green);
int dx = newx - startx;
int dy = newy - starty;
params.x += dx;
params.y += dy;
// 更新
wm.updateViewLayout(view, params);
// 对初始坐标重新赋值
startx = (int) event.getRawX();
starty = (int) event.getRawY();
}
break;
//手抬起的时候。
case MotionEvent.ACTION_UP:
if (isMove) {
isMove = false;
float halfScreen = screenWidth / 2;
if (startx <= halfScreen) {
//如果在左边的话,手抬起的时候,把x设为0;
params.x = 0;
wm.updateViewLayout(view, params);
iv_anzai.setImageResource(R.drawable.assist_anzai_left_green);
//保存为x=0;
editor.putFloat("x", 0);
isRight = false;
} else {
params.x = screenWidth;
wm.updateViewLayout(view, params);
iv_anzai.setImageResource(R.drawable.assist_anzai_right_green);
editor.putFloat("x", screenWidth);
isRight = true;
}
editor.putFloat("y", starty);
editor.putBoolean("isRight", isRight);
editor.commit();
} else {
//初始化的时候判断。
if (isRight) {
iv_anzai.setImageResource(R.drawable.assist_anzai_right_green);
} else {
iv_anzai.setImageResource(R.drawable.assist_anzai_left_green);
}
if (mOnClickListener != null) {
mOnClickListener.onClick(view);
}
}
break;
}
return true;
}
}
/**
* 安仔点击监听器,点击时候,出现悬浮框 点击事件就是在窗体wm中再添加一个view。
*
* @author malinkang
*
*/
private class MyOnClickListener implements OnClickListener {
public void onClick(View v) {
initFloatWindow();
createFloatWindow();
}
}
/**
* 初始化设置窗体
*/
private View floatView;
private LayoutParams params2;
private WindowManager floatWindow;
private void initFloatWindow() {
floatWindow = (WindowManager) getSystemService("window");
params2 = new LayoutParams();
//初始化设置ui。
floatView = initFloatUI();
params2.type = LayoutParams.TYPE_PHONE;
params2.format = PixelFormat.RGBA_8888;
params2.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_NOT_FOCUSABLE;
params2.x = 5;
params2.y = 25;
params2.height = 400;
params2.width = 320;
params2.gravity = Gravity.LEFT | Gravity.TOP;
}
private boolean floatWindowIsDisplay;
//创造浮动窗体
public void createFloatWindow() {
if (floatWindowIsDisplay)
return;
floatWindow.addView(floatView, params2);
floatWindowIsDisplay = true;
}
//移除浮动窗体
public void removeFloatWindow() {
if (!floatWindowIsDisplay)
return;
floatWindow.addView(floatView, params2);
floatWindowIsDisplay = false;
}
/**
* 初始化浮动窗体界面
*
* @return
*/
private List<View> views;
private SwitcherItemView switch_ringtone;
private SwitcherItemView switch_vibrate;
private List<AppInfo> appInfos;
private View initFloatUI() {
//
View view = View.inflate(getApplicationContext(),
R.layout.assist_float_window, null);
//得到viewpaper。子控件
ViewPager assist_viewpager = (ViewPager) view
.findViewById(R.id.assist_viewpager);
//new一个集合。
views = new ArrayList<View>();
//new 一个线性布局pager_1。
LinearLayout pager_1 = new LinearLayout(getApplicationContext());
pager_1.setOrientation(1);
//得到scrollview对象。
ScrollView assist_switcher_container = (ScrollView) View.inflate(
getApplicationContext(), R.layout.assist_switcher_container,
null);
//将scrollview加入线性布局中。
pager_1.addView(assist_switcher_container);
//
initFindView(assist_switcher_container);
LayoutInflater.from(getApplicationContext()).inflate(
R.layout.assist_process_clear, pager_1, true);
//向PagerAdapter添加的第一个view。向PagerAdapter
views.add(pager_1);
LinearLayout pager_2 = (LinearLayout) View.inflate(
getApplicationContext(), R.layout.assist_task_view, null);
//向pageradapter添加的第二个。
views.add(pager_2);
//获取pager2里面的gridview。
GridView float_grid = (GridView) pager_2.findViewById(R.id.float_grid);
//获取最近的recenttask。
appInfos = getRecentTask();
// gridview 中的适配器
MyAdapter adapter = new MyAdapter();
//给gridview设置适配器
float_grid.setAdapter(adapter);
//gridveiw子项设置监听
float_grid.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getApplicationContext(), position + "",
Toast.LENGTH_LONG).show();
}
});
MyPagerAdapter adapter2 = new MyPagerAdapter();
//给viewpaper设置适配器。2页。
assist_viewpager.setAdapter(adapter2);
return view;
}
/**
* 查找ScrollView上的控件SwitcherItemView
*
* @param view
*/
//查找
private void initFindView(ScrollView view) {
switch_ringtone = (SwitcherItemView) view
.findViewById(R.id.switch_ringtone);
switch_vibrate = (SwitcherItemView) view
.findViewById(R.id.switch_vibrate);
}
/**
* ViewPager适配器 PagerAdapter
*
* @author malinkang
*
*/
//
private class MyPagerAdapter extends PagerAdapter {
@Override
public int getCount() {
return 2;
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(views.get(position));
return views.get(position);
}
}
/**
* 设置
*
* @param v
*/
public void onClick(View v) {
//声音管理器
AudioManager am = (AudioManager) getApplicationContext()
.getSystemService(Context.AUDIO_SERVICE);
//震动管理器
Vibrator vibrator = (Vibrator) getApplicationContext()
.getSystemService(Context.VIBRATOR_SERVICE);
switch (v.getId()) {
case R.id.switch_ringtone:// 设置铃声
if (switch_ringtone.isSelected()) {
am.setRingerMode(AudioManager.RINGER_MODE_SILENT);
switch_ringtone.setSelected(false);
Toast.makeText(getApplicationContext(), "铃声已关闭", 0).show();
} else {
am.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
switch_ringtone.setSelected(true);
Toast.makeText(getApplicationContext(), "铃声已开启", 0).show();
}
break;
case R.id.switch_vibrate:// 设置手机震动
if (switch_vibrate.isSelected()) {
am.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
switch_vibrate.setSelected(false);
Toast.makeText(getApplicationContext(), "震动关闭", 0).show();
} else {
vibrator.vibrate(100);
am.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
switch_vibrate.setSelected(true);
Toast.makeText(getApplicationContext(), "震动已开启", 0).show();
}
break;
case R.id.switch_gps:// 设置GPS
break;
}
}
/**
* 显示最近任务的GridView适配器 BaseAdapter 显示gridview中的每一项。
*
* @author malinkang
*
*/
private class MyAdapter extends BaseAdapter {
public int getCount() {
return appInfos.size();
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
View view;
ViewHolder holder;
//复用convertview。
if (convertView != null && convertView instanceof LinearLayout) {
view = convertView;
//
holder = (ViewHolder) view.getTag();
} else {
//得到view。
view = View.inflate(getApplicationContext(),
R.layout.assist_task_item, null);
//对象。
holder = new ViewHolder();
//得到子控件,给子控件赋值。
holder.item_label = (TextView) view
.findViewById(R.id.item_label);
holder.item_icon = (ImageView) view
.findViewById(R.id.item_icon);
//给view设置tag。可以使用setTag把查找的view缓存起来方便多次重用
//View中的setTag(Onbect)表示给View添加一个格外的数据,以后可以用getTag()将这个数据取出来。
view.setTag(holder);
}
AppInfo appInfo = appInfos.get(position);
holder.item_icon.setImageDrawable(appInfo.getIco());
holder.item_label.setText(appInfo.getAppName());
return view;
}
}
static class ViewHolder {
TextView item_label;
ImageView item_icon;
}
/**
* 用于获取最近应用的信息
*
* @return
*/
public List<AppInfo> getRecentTask() {
ActivityManager am = (ActivityManager) getApplicationContext()
.getSystemService(Context.ACTIVITY_SERVICE);
PackageManager pm = getApplicationContext().getPackageManager();
//得到最近运行程序的集合
List<RecentTaskInfo> recentTaskInfos = am.getRecentTasks(64, 0);
List<AppInfo> appInfos = new ArrayList<AppInfo>();
AppInfo appInfo = null;
for (RecentTaskInfo recentTaskInfo : recentTaskInfos) {
appInfo = new AppInfo();
//这个intent可以将重新启动任务。将任务带向前台
Intent intent = recentTaskInfo.baseIntent;
// 查询是否有符合条件的activity。
ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
if (resolveInfo != null) {
//icon name packagename这3个信息构成一个实体。
Drawable appico = resolveInfo.loadIcon(pm);
appInfo.setIco(appico);
String appName = resolveInfo.loadLabel(pm).toString();
appInfo.setAppName(appName);
String packageName = resolveInfo.activityInfo.packageName;
appInfo.setPackageName(packageName);
appInfos.add(appInfo);
}
}
return appInfos;
}
/**
* 打开应用 传入包名就可以打开应用
*
* @param packageName
*/
private void startupApk(String packageName) {
// 开启这个应用程序的第一个activity.
try {
//通过包名得到包信息
PackageInfo packinfo = getPackageManager().getPackageInfo(
packageName, PackageManager.GET_ACTIVITIES);
//得到包里面的所有activity
ActivityInfo[] activityinfos = packinfo.activities;
if (activityinfos != null && activityinfos.length > 0) {
ActivityInfo activityinfo = activityinfos[0];
Intent intent = new Intent();
//intent.setClassName(arg1,arg2)中的arg1是被调用程序B的包名,arg2是B程序中目的activity的完整类名。
intent.setClassName(activityinfo.packageName, activityinfo.name);
startActivity(intent);
} else {
Toast.makeText(this, "无法开启当前应用", 0).show();
}
} catch (NameNotFoundException e) {
e.printStackTrace();
Toast.makeText(this, "无法开启当前应用", 0).show();
}
}
}
布局
package com.malinkang.AssistAnZai;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
//自定义布局
public class SwitcherItemView extends RelativeLayout {
private View view;
private TextView tv_switcher_label;
private ImageView iv_switcher_icon;
private Drawable switcher_icon;
private String switcher_label;
//带defStyle的构造方法。
public SwitcherItemView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView(context);
}
//带属性集的构造方法
public SwitcherItemView(Context context, AttributeSet attrs) {
super(context, attrs);
//得到控件的子对象。
initView(context);
//获取到TypedArray。传入的参数是values包下attrs.xml文件。
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SwitcherItemView);
//获取图片
switcher_icon = ta.getDrawable(R.styleable.SwitcherItemView_switcher_icon);
//获取文本
switcher_label = ta.getString(R.styleable.SwitcherItemView_switcher_label);
//iv设置图片资源
iv_switcher_icon.setImageDrawable(switcher_icon);
//tv设置文本资源
tv_switcher_label.setText(switcher_label);
}
public SwitcherItemView(Context context) {
super(context);
initView(context);
}
public void initView(Context context){
//通过inflate获取view对象。之后获取子对象。
view = View.inflate(context, R.layout.assist_switcher_item, this);
iv_switcher_icon = (ImageView) view.findViewById(R.id.switch_icon);
tv_switcher_label = (TextView) view.findViewById(R.id.switch_label);
}
}