Android 悬浮窗的实现源码

转载请标明出处:http://blog.csdn.net/pcaxb/article/details/48048529

悬浮窗的实现用到了一个Service、自定义View、Activity

效果图

悬浮窗的实现用到的权限:

    <!-- 仿360浮动插件需要的权限 -->
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <uses-permission android:name="com.android.vending.BILLING" />

在清单文件中注册服务

<service android:name="com.pca.nettraffic.MserServes" />

代码的实现

1.Activity的源码

package com.pca.nettraffic;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class WidgetMainActivity extends Activity {
	// 一个有只有一个按钮的activity

	private Button btn;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);

		setContentView(R.layout.activity_imitate_widget_main);
		btn = (Button) findViewById(R.id.btn);
		btn.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				funClick();
			}
		});
	}

	public void funClick() {
		// 按钮被点击
		this.startService(new Intent(getApplicationContext(), MserServes.class));
		// new TableShowView(this).fun(); 如果只是在activity中启动
		// 当activity跑去后台的时候[暂停态,或者销毁态] 我们设置的显示到桌面的view也会消失
		// 所以这里采用的是启动一个服务,服务中创建我们需要显示到table上的view,并将其注册到windowManager上
		this.finish();
	}

}

2.Service源码

package com.pca.nettraffic;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class MserServes extends Service {
	 //服务
    //这个类纯蛋疼用 只是为了在activity点击button后 在开启一个service   

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }  

    public void onCreate() {
    	//创建service时一个 实例化一个TableShowView对象并且调用他的fun()方法把它注册到windowManager上
        super.onCreate();
        new TableShowView(getApplicationContext()).fun();
        System.out.println("开启Mser服务......");
    }  

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        return super.onStartCommand(intent, flags, startId);
    }
}  

3.自定义View源码(TableShowView extends View)

package com.pca.nettraffic;

import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;

public class TableShowView extends View {
		// 如果是想显示歌词则继承TextView并复写ondraw方法。
		// 开启一个线程不断的调用ondraw方法去更改你所写的继承自TextView的内容
		// 这里随便写了个集成自view的= =这个不是重点

		Context						c;
		WindowManager				mWM;		// WindowManager
		WindowManager.LayoutParams	mWMParams;	// WindowManager参数
		View						win;
		int tag = 0;
		int oldOffsetX;
		int oldOffsetY;

		public TableShowView(Context context) {
			// TODO Auto-generated constructor stub
			super(context);
			c = context;
		}

		public void fun() {
			// 设置载入view WindowManager参数
			mWM = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
			win = LayoutInflater.from(c).inflate(R.layout.activity_imitate_widget_ctrl_window, null);
			win.setBackgroundColor(Color.TRANSPARENT);
			// 这里是随便载入的一个布局文件

			win.setOnTouchListener(new OnTouchListener() {
				// 触屏监听
				float	lastX, lastY;

				public boolean onTouch(View v, MotionEvent event) {
					final int action = event.getAction();

					float x = event.getX();
					float y = event.getY();

					if(tag == 0){
					   oldOffsetX= mWMParams.x; // 偏移量
					   oldOffsetY = mWMParams.y; // 偏移量
					}

					if (action == MotionEvent.ACTION_DOWN) {
						lastX = x;
						lastY = y;

					}
					else if (action == MotionEvent.ACTION_MOVE) {
						mWMParams.x += (int) (x - lastX); // 偏移量
						mWMParams.y += (int) (y - lastY); // 偏移量

						tag = 1;
						mWM.updateViewLayout(win, mWMParams);
					}

					else if (action ==  MotionEvent.ACTION_UP){
						int newOffsetX = mWMParams.x;
						int newOffsetY = mWMParams.y;
						if(oldOffsetX == newOffsetX && oldOffsetY == newOffsetY){
							Toast.makeText(c, "你点到我了……疼!!!!", 1).show();
						}else {
							tag = 0;
						}
					}
					return true;
				}
			});

			WindowManager wm = mWM;
			WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();
			mWMParams = wmParams;
			wmParams.type = 2002; // type是关键,这里的2002表示系统级窗口,你也可以试试2003。
			wmParams.flags = 40;// 这句设置桌面可控

			wmParams.width = 50;
			wmParams.height = 50;
			wmParams.format = -3; // 透明

			wm.addView(win, wmParams);// 这句是重点 给WindowManager中丢入刚才设置的值
										// 只有addview后才能显示到页面上去。
			// 注册到WindowManager win是要刚才随便载入的layout,wmParams是刚才设置的WindowManager参数集
			// 效果是将win注册到WindowManager中并且它的参数是wmParams中设置饿

		}

}

源码下载地址:http://download.csdn.net/detail/pcaxb/9057047

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-02 17:04:26

Android 悬浮窗的实现源码的相关文章

Android应用安全开发之源码安全

Android应用安全开发之源码安全 gh0stbo · 2016/01/21 10:24 0x00 简介 Android apk很容易通过逆向工程进行反编译,从而是其代码完全暴露给攻击者,使apk面临破解,软件逻辑修改,插入恶意代码,替换广告商ID等风险.我们可以采用以下方法对apk进行保护. 0x01 混淆保护 混淆是一种用来隐藏程序意图的技术,可以增加代码阅读的难度,使攻击者难以全面掌控app内部实现逻辑,从而增加逆向工程和破解的难度,防止知识产权被窃取. 代码混淆技术主要做了如下的工作:

Android # 4.0.x(1-3) 源码 下载 编译

Android 4.0源码下载方法:repo init -u https://android.googlesource.com/platform/manifest -b android-4.0.1_r1 官方下载页面:http://source.android.com/source/downloading.html Android SDK 4.0官方下载页面:http://developer.android.com/sdk/android-4.0.html android 4.0.3最新源码下载

Android应用Preference相关及源码浅析(Preference组件家族篇)

1 前言 前一篇(点我阅读前一篇<Android应用Preference相关及源码浅析(SharePreferences篇)>)我们讨论分析使用了Android的SharePreferences,相信看过的朋友都有了自己的感悟与理解,这一篇我们继续乘热打铁来说说SharePreferences的衍生品--Preference组件. 其实Preference组件大家一定不陌生,因为Android系统的Setting应用及我们市面上一些符合Android设计思想的应用的设置界面一般都会用它来实现,

Android贝壳单词客户端应用源码

该源码是Android贝壳单词客户端应用源码,贝壳单词 APP Android 客户端.背单词的时候我就想,市面上单词APP做得再好,用户不愿打开就根本没用.于是,「贝壳单词」用完全不一样的方式,让你在无意识无压力之中轻松地增加词汇量,从此,就算大学的英语课不上了,也不必再担心英语日渐倒退,因为你每一天都在无意识之中稳步进行. 可能在使用中使用到源码片段:http://code.662p.com/list/173_1.html [更新内容]1. 新增 可动态显示的公告栏,可以非常方便接收到最新应

ANDROID PAD版本 PHONE版本 源码有什么 区别?

ANDROID PAD版本 PHONE版本 源码有什么 区别? 直接把frameworks/base/core/res/res/values/config.xml里面的<bool name="config_voice_capable">false</bool>改为false

Android短信插入器源码

package com.examp.createsms; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentValues; import android.net.Uri; import android.os.Bundle; public class MainActivity extends Activity { @Override protected

Android手游斗地主完整源码

Android手游斗地主完整源码 Android手游斗地主完整源码(支持单机和网络对战) 下载地址:http://www.devstore.cn/code/info/943.html 运行截图:

android 仿网易新闻客户端源码都有

原文:android 仿网易新闻客户端源码都有 android 仿网易新闻服务端源码 源代码下载地址: http://www.zuidaima.com/share/1550463560944640.htm http://www.zuidaima.com/share/1550463561206784.htm android 仿网易新闻 客户端和服务端 源码都有 ,有些功能还未实现,因为文件有点大,所以分为2次上传  java源代码截图:

Android View 事件分发机制源码详解(View篇)

前言 在Android View 事件分发机制源码详解(ViewGroup篇)一文中,主要对ViewGroup#dispatchTouchEvent的源码做了相应的解析,其中说到在ViewGroup把事件传递给子View的时候,会调用子View的dispatchTouchEvent,这时分两种情况,如果子View也是一个ViewGroup那么再执行同样的流程继续把事件分发下去,即调用ViewGroup#dispatchTouchEvent:如果子View只是单纯的一个View,那么调用的是Vie