Android之來電秀實(shí)戰(zhàn)示例
正文
簡單的說下實(shí)現(xiàn)來電秀的大概原理流程:首先通過監(jiān)聽來電狀態(tài),通過攔截來電然后在窗口彈出一層系統(tǒng)級(jí)別的彈窗,這層彈窗即是來電秀。
先來兩張效果圖:


下面來說下實(shí)現(xiàn),因?yàn)樯逃玫脑颍荒苤苯淤N代碼,所以在這里,會(huì)貼一些比較核心的代碼,大概分為五個(gè)步驟:
第一:監(jiān)聽來電狀態(tài)
/**
* 電話狀態(tài)監(jiān)聽(來電或去電)
*
* @author Jenly
*
*/
public class PhoneStateReceiver extends BroadcastReceiver {
public static final String PHONE_STATE = "android.intent.action.PHONE_STATE";
@Override
public void onReceive(Context context, Intent intent) {
LogUtils.d(intent.getAction());
context.startService(new Intent(context,CallShowService.class));
}
}這是一個(gè)廣播接收器,用來接收手機(jī)來電狀態(tài)的,把接收到的狀態(tài)發(fā)送給CallShowService服務(wù)來做相應(yīng)的處理
第二:通過手機(jī)狀態(tài)來做不同的處理
CallShowService.class是一個(gè)來電秀服務(wù)(CallShowService extends Service),里面的主要核心代碼是通過監(jiān)聽來電狀態(tài)來做出相應(yīng)的處理,如:彈屏
下面是CallShowService幾個(gè)比較核心的代碼:
@Override
public void onCreate() {
super.onCreate();
isRunning = true;
initPhoneStateListener();
callShowView = CallShowView.getInstance();
}/**
* 初始化電話狀態(tài)監(jiān)聽
*/
private void initPhoneStateListener(){
phoneStateListener = new PhoneStateListener(){
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
phoneState = state;
if(isEnable){//啟用
switch (state) {
case TelephonyManager.CALL_STATE_IDLE://待機(jī)時(shí)(即無電話時(shí),掛斷時(shí)會(huì)調(diào)用)
LogUtils.d("CALL_STATE_IDLE");
dismiss();//關(guān)閉來電秀
break;
case TelephonyManager.CALL_STATE_OFFHOOK://摘機(jī)(接聽)
LogUtils.d("CALL_STATE_OFFHOOK");
callShow();//顯示來電秀
break;
case TelephonyManager.CALL_STATE_RINGING://響鈴(來電)
LogUtils.d("CALL_STATE_RINGING");
isCalling = false;
phoneNumber = incomingNumber;
LogUtils.d("incomingNumber:"+ incomingNumber);//來電號(hào)碼
callShow();//顯示來電秀
break;
default:
break;
}
}
}
};
//--------------------------
telephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
//設(shè)置監(jiān)聽器
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent!=null && Intent.ACTION_NEW_OUTGOING_CALL.equals(intent.getAction())){//去電
phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
LogUtils.d("Calling..."+phoneNumber);
isCalling = true;
}
return super.onStartCommand(intent, START_STICKY, startId);
}第三:來電秀界面的實(shí)現(xiàn)了
CallShowView 來電秀界面 (CallShowView extends View),里面彈屏的核心代碼:
private void initViews() {
context = getContext();
windowManager = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
int width = windowManager.getDefaultDisplay().getWidth();
int height = windowManager.getDefaultDisplay().getHeight();
// -------------
params = new LayoutParams();
params.gravity = Gravity.LEFT | Gravity.TOP;
params.x = 0;
params.y = 0;
params.width = width;
params.height = height;
params.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
// 設(shè)置圖片格式,效果為背景透明
params.format = PixelFormat.TRANSLUCENT;
// 設(shè)置Window flag 系統(tǒng)級(jí)彈框 | 覆蓋表層
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
// 不可聚集(不讓返回鍵) | 全屏 | 透明標(biāo)狀態(tài)欄
params.flags = LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN ;
initCalledView();
}第四:開機(jī)自動(dòng)啟動(dòng)
/**
* 自動(dòng)啟動(dòng)
* @author Jenly
*/
public class AutoStartReceiver extends BroadcastReceiver {
public static final String AUTO_START_RECEIVER = "jenly.autostart_action";
@Override
public void onReceive(Context context, Intent intent) {
LogUtils.d("AutoStartReceiver");
if(!CallShowService.isRunning)
startCallShowService(context, intent);
}
private void startCallShowService(Context context, Intent intent) {
intent.setClass(context, CallShowService.class);
context.startService(intent);
}
}在CallShowService的生命周期里面需要加上一句核心的代碼,保證CallShowService不被進(jìn)程殺死,如下:
@Override
public void onDestroy() {
isRunning = false;
sendBroadcast(new Intent(AutoStartReceiver.AUTO_START_RECEIVER));
super.onDestroy();
}第五:注冊這些四大組件和申請用到的一些權(quán)限
<!-- 電話狀態(tài)接收廣播 -->
<receiver android:name=".service.PhoneStateReceiver" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
<receiver android:name=".service.AutoStartReceiver" >
<intent-filter android:priority="1000">
<action android:name="android.intent.action.RECEIVE_BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
<action android:name="jenly.autostart_action" />
</intent-filter>
</receiver>
<service android:name=".service.CallShowService"
android:enabled="true" >
<intent-filter android:priority="1000" >
<action android:name=".service.CallShowService" />
</intent-filter>
</service><uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 彈出窗口權(quán)限 -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />這樣來電秀算是基本實(shí)現(xiàn)了,簡單的總結(jié)一下幾個(gè)重要的點(diǎn):
1、手機(jī)來電狀態(tài)的監(jiān)聽攔截、
2、來去電彈屏、
3、開機(jī)啟動(dòng)保證彈屏服務(wù)不被后臺(tái)殺死、
今天就先到這里了,后續(xù)會(huì)把來電秀界面的電話的接聽與掛機(jī)也寫出來,更多關(guān)于Android來電秀的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android AlertDialog多種創(chuàng)建方式案例詳解
這篇文章主要介紹了Android AlertDialog多種創(chuàng)建方式案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
Android退出應(yīng)用最優(yōu)雅的方式(改進(jìn)版)
這篇文章主要介紹了Android退出應(yīng)用最優(yōu)雅的方式,改進(jìn)版,感興趣的小伙伴們可以參考一下2016-01-01
FragmentTabHost FrameLayout實(shí)現(xiàn)底部導(dǎo)航欄
這篇文章主要為大家詳細(xì)介紹了FragmentTabHost和FrameLayout實(shí)現(xiàn)底部導(dǎo)航欄,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
基于Android實(shí)現(xiàn)ListView圓角效果
這篇文章主要為大家詳細(xì)介紹了基于Android實(shí)現(xiàn)ListView圓角效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-06-06
ionic App 解決android端在真機(jī)上tab處于頂部的問題
這篇文章主要介紹了ionic App 解決android端在真機(jī)上tab處于頂部的問題的相關(guān)資料,需要的朋友可以參考下2017-06-06
Android導(dǎo)航欄功能項(xiàng)的顯示與屏蔽介紹
大家好,本篇文章主要講的是Android導(dǎo)航欄功能項(xiàng)的顯示與屏蔽介紹,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12

