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


下面來(lái)說(shuō)下實(shí)現(xiàn),因?yàn)樯逃玫脑?,不能直接貼代碼,所以在這里,會(huì)貼一些比較核心的代碼,大概分為五個(gè)步驟:
第一:監(jiān)聽(tīng)來(lái)電狀態(tài)
/**
* 電話狀態(tài)監(jiān)聽(tīng)(來(lái)電或去電)
*
* @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è)廣播接收器,用來(lái)接收手機(jī)來(lái)電狀態(tài)的,把接收到的狀態(tài)發(fā)送給CallShowService服務(wù)來(lái)做相應(yīng)的處理
第二:通過(guò)手機(jī)狀態(tài)來(lái)做不同的處理
CallShowService.class是一個(gè)來(lái)電秀服務(wù)(CallShowService extends Service),里面的主要核心代碼是通過(guò)監(jiān)聽(tīng)來(lái)電狀態(tài)來(lái)做出相應(yīng)的處理,如:彈屏
下面是CallShowService幾個(gè)比較核心的代碼:
@Override
public void onCreate() {
super.onCreate();
isRunning = true;
initPhoneStateListener();
callShowView = CallShowView.getInstance();
}/**
* 初始化電話狀態(tài)監(jiān)聽(tīng)
*/
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í)(即無(wú)電話時(shí),掛斷時(shí)會(huì)調(diào)用)
LogUtils.d("CALL_STATE_IDLE");
dismiss();//關(guān)閉來(lái)電秀
break;
case TelephonyManager.CALL_STATE_OFFHOOK://摘機(jī)(接聽(tīng))
LogUtils.d("CALL_STATE_OFFHOOK");
callShow();//顯示來(lái)電秀
break;
case TelephonyManager.CALL_STATE_RINGING://響鈴(來(lái)電)
LogUtils.d("CALL_STATE_RINGING");
isCalling = false;
phoneNumber = incomingNumber;
LogUtils.d("incomingNumber:"+ incomingNumber);//來(lái)電號(hào)碼
callShow();//顯示來(lái)電秀
break;
default:
break;
}
}
}
};
//--------------------------
telephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
//設(shè)置監(jiān)聽(tīng)器
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);
}第三:來(lái)電秀界面的實(shí)現(xiàn)了
CallShowView 來(lái)電秀界面 (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();
}第四:開(kāi)機(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();
}第五:注冊(cè)這些四大組件和申請(qǐng)用到的一些權(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" />這樣來(lái)電秀算是基本實(shí)現(xiàn)了,簡(jiǎn)單的總結(jié)一下幾個(gè)重要的點(diǎn):
1、手機(jī)來(lái)電狀態(tài)的監(jiān)聽(tīng)攔截、
2、來(lái)去電彈屏、
3、開(kāi)機(jī)啟動(dòng)保證彈屏服務(wù)不被后臺(tái)殺死、
今天就先到這里了,后續(xù)會(huì)把來(lái)電秀界面的電話的接聽(tīng)與掛機(jī)也寫出來(lái),更多關(guān)于Android來(lái)電秀的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解Android ScrollView嵌套EditText出現(xiàn)的滑動(dòng)問(wèn)題
本篇文章主要介紹了詳解ScrollView嵌套EditText出現(xiàn)的滑動(dòng)問(wèn)題,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Android Studio無(wú)法打開(kāi)得問(wèn)題解決方法
這篇文章主要詳細(xì)介紹了Android Studio無(wú)法打開(kāi)問(wèn)題解決辦法,文中有詳細(xì)的解決步驟和圖文介紹,對(duì)我們解決這個(gè)問(wèn)題有一定的幫助,需要的朋友可以參考下2023-07-07
親自動(dòng)手實(shí)現(xiàn)Android App插件化
這篇文章主要教大家親自動(dòng)手實(shí)現(xiàn)Android App插件化,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12
android Gallery組件實(shí)現(xiàn)的iPhone圖片滑動(dòng)效果實(shí)例
這篇文章主要介紹了android Gallery組件實(shí)現(xiàn)的iPhone圖片滑動(dòng)效果實(shí)例,即相冊(cè)內(nèi)的圖片實(shí)現(xiàn)可左右滑動(dòng)的效果,需要的朋友可以參考下2014-07-07
Android藍(lán)牙通信聊天實(shí)現(xiàn)發(fā)送和接受功能
這篇文章主要為大家詳細(xì)介紹了Android藍(lán)牙通信聊天實(shí)現(xiàn)發(fā)送和接受功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-07-07
Android之Notification的多種用法實(shí)例
本篇文章主要介紹了Android之Notification的多種用法實(shí)例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12
Android 開(kāi)發(fā)使用PopupWindow實(shí)現(xiàn)彈出警告框的復(fù)用類示例
這篇文章主要介紹了Android 開(kāi)發(fā)使用PopupWindow實(shí)現(xiàn)彈出警告框的復(fù)用類,結(jié)合實(shí)例形式分析了Android基于PopupWindow彈出警告框的復(fù)用類具體布局與功能實(shí)現(xiàn)技巧,需要的朋友可以參考下2020-05-05
Android SQLite數(shù)據(jù)庫(kù)基本操作方法
本篇文章主要介紹了Android SQLite數(shù)據(jù)庫(kù)基本操作方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02

