Android之來電秀實戰(zhàn)示例
正文
簡單的說下實現(xiàn)來電秀的大概原理流程:首先通過監(jiān)聽來電狀態(tài),通過攔截來電然后在窗口彈出一層系統(tǒng)級別的彈窗,這層彈窗即是來電秀。
先來兩張效果圖:
下面來說下實現(xiàn),因為商用的原因,不能直接貼代碼,所以在這里,會貼一些比較核心的代碼,大概分為五個步驟:
第一:監(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)); } }
這是一個廣播接收器,用來接收手機來電狀態(tài)的,把接收到的狀態(tài)發(fā)送給CallShowService服務(wù)來做相應(yīng)的處理
第二:通過手機狀態(tài)來做不同的處理
CallShowService.class是一個來電秀服務(wù)(CallShowService extends Service),里面的主要核心代碼是通過監(jiān)聽來電狀態(tài)來做出相應(yīng)的處理,如:彈屏
下面是CallShowService幾個比較核心的代碼:
@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://待機時(即無電話時,掛斷時會調(diào)用) LogUtils.d("CALL_STATE_IDLE"); dismiss();//關(guān)閉來電秀 break; case TelephonyManager.CALL_STATE_OFFHOOK://摘機(接聽) 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);//來電號碼 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); }
第三:來電秀界面的實現(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)級彈框 | 覆蓋表層 params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; // 不可聚集(不讓返回鍵) | 全屏 | 透明標狀態(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(); }
第四:開機自動啟動
/** * 自動啟動 * @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不被進程殺死,如下:
@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" />
這樣來電秀算是基本實現(xiàn)了,簡單的總結(jié)一下幾個重要的點:
1、手機來電狀態(tài)的監(jiān)聽攔截、
2、來去電彈屏、
3、開機啟動保證彈屏服務(wù)不被后臺殺死、
今天就先到這里了,后續(xù)會把來電秀界面的電話的接聽與掛機也寫出來,更多關(guān)于Android來電秀的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android AlertDialog多種創(chuàng)建方式案例詳解
這篇文章主要介紹了Android AlertDialog多種創(chuàng)建方式案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-08-08Android退出應(yīng)用最優(yōu)雅的方式(改進版)
這篇文章主要介紹了Android退出應(yīng)用最優(yōu)雅的方式,改進版,感興趣的小伙伴們可以參考一下2016-01-01FragmentTabHost FrameLayout實現(xiàn)底部導(dǎo)航欄
這篇文章主要為大家詳細介紹了FragmentTabHost和FrameLayout實現(xiàn)底部導(dǎo)航欄,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03ionic App 解決android端在真機上tab處于頂部的問題
這篇文章主要介紹了ionic App 解決android端在真機上tab處于頂部的問題的相關(guān)資料,需要的朋友可以參考下2017-06-06