先看下效果图

说下思路:

1:监听来电广播

2:根据来电号码,和本地数据库做匹配,有记录的,则提取出头像、名字、职位,生成悬浮窗

3:监听来电广播,如果当前行为是空闲的(没有任何通话行为),则删除掉悬浮窗。

tips:原先使用服务来监听,可惜在后台服务锁屏后一段时间很容易被杀死,试过各种办法无效,所以采用监听广播的方式,但是在魅族手机上测试时,发现需要允许(开机自启动),否则一样监听不到广播

说了思路之后,就贴上代码了,逻辑很简单,就不多赘述了。

1:监听来电类

记得在AndroidManifest.xml加上权限声明

 <receiver android:name=".call.IncomingCallBroadCastReceiver">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
package zhexian.app.smartcall.call;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.view.View;
import android.view.WindowManager; import zhexian.app.smartcall.base.BaseApplication; public class IncomingCallBroadCastReceiver extends BroadcastReceiver { private static View addedView = null; @Override
public void onReceive(Context context, Intent intent) {
TelephonyManager tManager = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);
int callState = tManager.getCallState(); switch (callState) {
case TelephonyManager.CALL_STATE_RINGING:
removeView(context);
CallFlatWindowManager windowManager = new CallFlatWindowManager((BaseApplication) context.getApplicationContext());
String incomingNumber = intent.getStringExtra("incoming_number");
addedView = windowManager.OnCall(incomingNumber);
break; case TelephonyManager.CALL_STATE_IDLE:
removeView(context);
break;
}
} void removeView(Context context) {
if (addedView == null)
return; try {
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
windowManager.removeViewImmediate(addedView);
} catch (Exception e) {
e.printStackTrace();
} finally {
addedView = null;
} }
}

悬浮窗实现代码也一并贴出,仅供各位参考

通过WindowManager,生成一个不可触摸的窗体

package zhexian.app.smartcall.call;

import android.content.Context;
import android.graphics.PixelFormat;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView; import zhexian.app.smartcall.R;
import zhexian.app.smartcall.base.BaseApplication;
import zhexian.app.smartcall.lib.ZContact;
import zhexian.app.smartcall.lib.ZIO;
import zhexian.app.smartcall.lib.ZString;
import zhexian.app.smartcall.tools.Utils; /**
* 来电悬浮窗管理类
*/
public class CallFlatWindowManager {
private int IMAGE_SIZE = 128;
private WindowManager mWindowManager;
private WindowManager.LayoutParams layoutParams;
private View view;
private TextView mUserName;
private TextView mJob;
private BaseApplication baseApp;
private ImageView imageView; public CallFlatWindowManager(BaseApplication baseApp) {
this.baseApp = baseApp;
initWindow();
ContactSQLHelper.Init(baseApp); } public View OnCall(String incomingNumber) { if (ZContact.isPhoneExists(baseApp, incomingNumber))
return null; CallUserEntity entity = ContactSQLHelper.getInstance().getContact(incomingNumber); if (entity == null)
return null; return attachWindow(entity.getName(), entity.getJob(), entity.getAvatarUrl());
} private View attachWindow(String userName, String job, String url) {
mUserName.setText(userName);
mJob.setText(job);
loadImage(url);
mWindowManager.addView(view, layoutParams); return view;
} private void initWindow() {
mWindowManager = (WindowManager) baseApp.getSystemService(Context.WINDOW_SERVICE);
layoutParams = new WindowManager.LayoutParams();
layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
layoutParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
layoutParams.format = PixelFormat.RGBA_8888;
layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; LayoutInflater inflater = (LayoutInflater) baseApp.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.call_flat_window, null); mUserName = (TextView) view.findViewById(R.id.flat_user_name);
imageView = (ImageView) view.findViewById(R.id.flat_user_avatar);
mJob = (TextView) view.findViewById(R.id.flat_user_job);
} private void loadImage(String url) { if (url.isEmpty()) {
imageView.setVisibility(View.GONE);
return;
}
String cachedUrl = ZString.getFileCachedDir(url, baseApp.getFilePath()); if (ZIO.isExist(cachedUrl))
imageView.setImageBitmap(Utils.getScaledBitMap(cachedUrl, IMAGE_SIZE, IMAGE_SIZE));
else
imageView.setVisibility(View.GONE);
}
}

【android】来电悬浮窗的更多相关文章

  1. Android WindowManager悬浮窗:不需要申请权限实现悬浮

     Android WindowManager悬浮窗:不需要申请权限实现悬浮 附录文章1介绍了Android平台上的悬浮窗WindowManager,WindowManager悬浮窗可以悬浮在And ...

  2. Android 之 悬浮窗

    昨天研究Android的悬浮窗,遇到一个问题,研究了一天,总算找到结症了,原因非常坑人..... 问题是这样的,我想要将悬浮窗展现在桌面或其他应用之上,我的开发机子用的是MIUI,结果发现在机子上无论 ...

  3. Android 8悬浮窗适配

    背景 APP推出时,提示是退出还是更改账号,这个提示框是系统级别的.然而我的Android 9 会崩溃,宁外一个小伙伴Android 7运行理想.报错提示permission denied for w ...

  4. android桌面悬浮窗仿QQ手机管家加速效果

    主要还是用到了WindowManager对桌面悬浮进行管理. 需要一个火箭的悬浮窗 一个发射台悬浮窗  ,判断火箭是否放到了发射台,如果放上了,则使用AsyTask 慢慢将火箭的图片往上移.结束后., ...

  5. android桌面悬浮窗实现

                            首先是一个小的悬浮窗显示的是当前使用了百分之多少的内存,点击一下小悬浮窗,就会弹出一个大的悬浮窗,可以一键加速.好,我们现在就来模拟实现一下类似的效果. ...

  6. Android 桌面悬浮窗效果实现,仿360手机卫士悬浮窗效果

    首先是一个小的悬浮窗显示的是当前使用了百分之多少的内存,点击一下小悬浮窗,就会弹出一个大的悬浮窗,可以一键加速.好,我们现在就来模拟实现一下类似的效果. 先谈一下基本的实现原理,这种桌面悬浮窗的效果很 ...

  7. Android桌面悬浮窗效果实现,仿360手机卫士悬浮窗效果

    大家好,今天给大家带来一个仿360手机卫士悬浮窗效果的教程,在开始之前请允许我说几句不相干的废话. 不知不觉我发现自己接触Android已有近三个年头了,期间各种的成长少不了各位高手的帮助,总是有很多 ...

  8. Android 关于悬浮窗权限的问题

    正常情况下的处理: dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)以及在清单文件中添加 <use ...

  9. Android 悬浮窗 System Alert Window

    悬浮窗能显示在其他应用上方.桌面系统例如Windows,macOS,Ubuntu,打开的程序能以窗口形式显示在屏幕上. 受限于屏幕大小,安卓系统中主要使用多任务切换的方式和分屏的方式.视频播放,视频对 ...

随机推荐

  1. TArray<uint8>转FString

    void ARamaUDPReceiver::Recv(const FArrayReaderPtr& ArrayReaderPtr, const FIPv4Endpoint& EndP ...

  2. 第十四篇:Apriori 关联分析算法原理分析与代码实现

    前言 想必大家都听过数据挖掘领域那个经典的故事 - "啤酒与尿布" 的故事. 那么,具体是怎么从海量销售信息中挖掘出啤酒和尿布之间的关系呢? 这就是关联分析所要完成的任务了. 本文 ...

  3. 重写equals()方法也要重写hashcode()方法

    如果我们对equals方法进行了重写,建议一定要对hashCode方法重写,以保证相同的对象返回相同的hash值,不同的对象返回不同的hash值.

  4. IOS内购支付服务器验证模式

    IOS 内购支付两种模式: 内置模式 服务器模式 内置模式的流程: app从app store 获取产品信息 用户选择需要购买的产品 app发送支付请求到app store app store 处理支 ...

  5. eclipse 设置 @author @version等注释模板

    eclipse->window->preference->java->code styple->code template->Code->New Java f ...

  6. Android上几种Animation和多个动画同时播放以ScaleAnimation应用详解

    在API Demo的View->Animation下可以找到四个Animation的Demo,第一个3D Translate比较复杂,最后再讲,先讲第2个Interpolator.该Activi ...

  7. 第一个MapReduce的例子

    第一个MapReduce的例子 Hadoop Guide的第一个MapReduce的例子是处理气象数据的(数据来源ncdc),终于跑通了.总结一下步骤,安装hadoop不在本文中介绍 1 数据预处理 ...

  8. SaltStack数据系统-Grains

    上一篇:SaltStack配置管理 granis:谷粒 pillar:柱子 grains是salt的一个组件,存放minion启动时候收集的信息(状态信息) 查看 salt '*' grains.it ...

  9. intellij idea 编码设置(乱码问题)

    一般把编辑器设置为 utf-8 如下设置: file-->setting-->editor-->file encodings-->

  10. 原型模式(Prototype Pattern)--对象的克隆

    定义:使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象; 原型类的核心在于如何实现克隆方法: 能够实现克隆的Java类必须实现一个标识接口Cloneable,表示这个类支持被复制; 通 ...