[¾Èµå·ÎÀ̵å/Android]Àüȼö½Å½Ã ÀüȹøÈ£ °¡Á®¿Í¼ Æ˾÷À¸·Î ¶ç¿ì´Â ¹æ¹ý
Á¦°¡ ¿î¿µÇÏ°í ÀÖ´Â À¯Æ©ºê ä³Î '°³¹ßÀÚ Å×µå¹Ú'¿¡µµ ¸¹Àº °ü½É ºÎŹµå·Á¿ä.
½ºÅ¸Æ®¾÷/°³¹ßÀÚ/IT °ü·ÃµÈ ¿©·¯ ¿µ»óÀ» ¿Ã¸®°í ÀÖ½À´Ï´Ù.
¿µ»óº¸·¯°¡±â
Àú´Â ¸ð¸£´Â ÀüȹøÈ£·Î °É·Á¿À´Â ÀüÈ´Â Àß ¹ÞÁö ¾Ê½À´Ï´Ù.
ÇÏÁö¸¸ Áß°í°Å·¡¸¦ ÇϱâÀ§ÇØ Áß°í¹°°ÇÀ» ¿©·¯ »çÀÌÆ®¿¡ ¿Ã·ÁµÎ¾úÀ»¶§´Â Ȥ½Ã ±¸¸ÅÀÚ°¡ ÀüÈÇÑ°ÍÀϼöµµ Àֱ⶧¹®¿¡ ±× ½Ã±â¿¡´Â °É·Á¿À´Â Àüȸ¦ ²À²À ¹Þ½À´Ï´Ù.
¼¿ÆùÀ̶ó´Â Áß°íÆù °Å·¡Áß°³¼ºñ½º¿¡¼´Â ³»°¡ ¿Ã·ÁµÐ Áß°íÆù ÆǸűÛÀ» º¸°í ±¸¸ÅÀÚ°¡ ÀüÈÇϴ°æ¿ì ¾Æ·¡ À̹ÌÁöó·³ Á¤º¸¸¦ ¾Ë·ÁÁÝ´Ï´Ù.
ÀÌ·¯ÇÑ °æ¿ì ¸ð¸£´Â ¹øÈ£ÀÌ´õ¶óµµ ³» ÆǸűÛÀ» º¸°í ¿¬¶ôÇÑ »ç¶÷ÀÓÀ» ¾Ë ¼ö Àֱ⠶§¹®¿¡ ¾È½ÉÇÏ°í Àüȸ¦ ¹ÞÀ» ¼ö ÀÖ½À´Ï´Ù.
¿äÁò ¸¹ÀÌ ¾²°íÀÖ´Â ÈÄÈijª ÈĽºÄÝ °°Àº °æ¿ìµµ ÀÌ¿Í ºñ½ÁÇÏ°Ô ÀüÈ°¡ °É·Á¿À´Â°æ¿ì¸¦ °¨ÁöÇؼ ÇØ´çÀüȹøÈ£°¡ ½ºÆÔÀÎÁö ¾Æ´ÑÁö¸¦ È®ÀÎÇÒ ¼ö ÀÖ½À´Ï´Ù.
¿©±â¼ ÀÌ¿ëµÇ´Â ¾Èµå·ÎÀ̵忡¼ÀÇ ±â´ÉÀº BroadcastReceiver, Service ÀÔ´Ï´Ù.
´ëºÎºÐ ÀÌ·¯ÇÑ ¼ºñ½ºµéÀÇ µ¿ÀÛ¼ø¼´Â ¾Æ·¡¿Í °°½À´Ï´Ù.
1. ÀüÈ°¡ ¿À´Â°æ¿ì °¨Áö¸¦ À§ÇÑ BroadcastReceiver »ý¼º ¹× µî·Ï
2. ¾ÛÀÌ ½ÇÇàÁßÀÌÁö ¾ÊÀº°æ¿ì¿¡µµ ±â´ÉÀ» ½ÇÇàÇϱâÀ§ÇÑ Service »ý¼º ¹× µî·Ï
3. ¶ç¿öÁ٠ȸéÀÇ ·¹À̾ƿô »ý¼º ¹× Ãß°¡
±×·³ BroadcastReceiver, Service¸¦ ÀÌ¿ëÇؼ ÀüÈ°¡ °É·Á¿À´Â °æ¿ì °É·Á¿Â ÀüȹøÈ£¸¦ Æ˾÷À¸·Î ¶ç¿ö¼ º¸¿©ÁÖ´Â ¿¹Á¦¸¦ ¸¸µé¾î º¸°Ú½À´Ï´Ù.
BroadcastReceiver
ÀüÈ°¡ ¿À´Â»óȲÀ» °¨ÁöÇϱâ À§ÇØ ÀüÈ»óŸ¦ ÀÐÀ»¼öÀÖ´Â ±ÇÇÑÀ» Manifest¿¡ Ãß°¡ÇØÁÖ¾î¾ß ÇÕ´Ï´Ù.
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
¶ÇÇÑ, receiverµµ Ãß°¡ÇØ ÁÝ´Ï´Ù.
<receiver android:name=".IncomingCallBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
</receiver>
BroadcastReceiverÀÇ onReceive()¿¡¼ ÀüÈ°¡ ¿À´Â°æ¿ì¸¦ °¨ÁöÇÏ°í Service¸¦ ½ÇÇàÇÏ´Â ºÎºÐÀ» ¸¸µé¾î ÁÝ´Ï´Ù.
¿©±â¼´Â ÅëȺ§ÀÌ ¿ï¸®´Â °æ¿ì °É·Á¿Â ÀüȹøÈ£¸¦ ¾Ë¾Æ³½µÚ, ±× ÀüȹøÈ£¸¦ Service·Î ³Ñ°ÜÁÖ¸é¼ Service¸¦ ½ÇÇàÇϵµ·Ï ÇÏ°Ú½À´Ï´Ù.
if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) {
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
final String phone_number = PhoneNumberUtils.formatNumber(incomingNumber);
Intent serviceIntent = new Intent(context, CallingService.class);
serviceIntent.putExtra(CallingService.EXTRA_CALL_NUMBER, phone_number);
context.startService(serviceIntent);
}
(Âü°í)
TelephonyManager.EXTRA_STATE_IDLE: ÅëÈÁ¾·á ȤÀº ÅëȺ§ Á¾·á
TelephonyManager.EXTRA_STATE_RINGING: ÅëȺ§ ¿ï¸®´ÂÁß
TelephonyManager.EXTRA_STATE_OFFHOOK: ÅëÈÁß
#ÁÖÀÇ
Á¤È®ÇÑ ÀÌÀ¯´Â ¾Ë ¼ö ¾øÁö¸¸ ½ÇÁ¦ BroadcastReceiver°¡ ¿©·¯¹ø È£ÃâµÇ´Â °æ¿ì¸¦ º¼ ¼ö ÀÖ½À´Ï´Ù.
±¸±Û¸µÀ» Çغ¸¸é Àú»Ó¸¸ ¾Æ´Ï¶ó ¸¹Àº »ç¶÷µéÀÌ ÀÌ·¯ÇÑ ¹®Á¦·Î ¾î·Á¿òÀ» °Þ°í ÀÖ½À´Ï´Ù.
ÀÌ·¸°ÔµÇ¸é ¿ì¸®°¡ ÀǵµÇÑ´ë·Î µÇÁö¾Ê°í ¼ºñ½º°¡ ¿©·¯¹ø È£ÃâµÇ´Â »óȲÀ» ¹ß»ý½ÃÅ°±âµµ ÇÕ´Ï´Ù.
À̸¦ ÇØ°áÇϱâ À§ÇØ static º¯¼ö¸¦ Çϳª µÎ°í³ª¼ ÇØ´ç º¯¼öÀÇ »óÅ°¡ º¯°æµÉ¶§¿¡¸¸ ½ÇÁ¦ º¯°æµÊÀ» °¨ÁöÇÏ°í ´ÙÀ½µ¿ÀÛÀ» ½ÇÇàÇϵµ·Ï ÇØÁÖ¾ú½À´Ï´Ù.
private static String mLastState;
if (state.equals(mLastState)) {
return;
} else {
mLastState = state;
}
(Âü°í: http://mmarvick.github.io/blog/blog/lollipop-multiple-broadcastreceiver-call-state/ )
Layout
Æ˾÷À¸·Î º¸¿©ÁÙ layout xmlÀ» ¸¸µé¾îÁÝ´Ï´Ù.
¿©±â¼´Â °£´ÜÇÏ°Ô °É·Á¿Â ÀüȹøÈ£¸¦º¸¿©ÁÖ°í Æ˾÷âÀ» Á¾·áÇÒ¼ö ÀÖ´Â X¹öÆ°À» ¸¸µé¾î µÎ°Ú½À´Ï´Ù.
Service
Manifest¿¡ Service¸¦ Ãß°¡ÇØÁÝ´Ï´Ù.
<service android:name=".CallingService"/>
ServiceÀÇ onCreate()¿¡¼ Æ˾÷ÀÇ Å©±â¿Í °¢Á¾ Æ˾÷°ú °ü·ÃµÈ ¼³Á¤µéÀ» ¼¼ÆÃÇØÁÝ´Ï´Ù.
¿©±â¼´Â Æ˾÷Å©±âÀÇ °¡·Î°¡ ȸéÀÇ 90%¸¸ ä¿ìµµ·Ï ¼³Á¤ÇØÁÖ¾ú½À´Ï´Ù.
±×¸®°í À§¿¡¼ ¸¸µé¾îµÐ popup layout xmlÀ» °¡Á®¿É´Ï´Ù.
@Override
public void onCreate() {
super.onCreate();
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
int width = (int) (display.getWidth() * 0.9); //Display »çÀÌÁîÀÇ 90%
params = new WindowManager.LayoutParams(
width,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON,
PixelFormat.TRANSLUCENT);
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
rootView = layoutInflater.inflate(R.layout.call_popup_top, null);
ButterKnife.inject(this, rootView);
setDraggable();
}
setDragable()ÇÔ¼ö¿¡¼´Â Æ˾÷View¿¡ setOnTouchListener¸¦ Ãß°¡Çؼ À̵¿½Ãų ¼ö ÀÖµµ·Ï ¼³Á¤ÇØÁÝ´Ï´Ù.
Æ˾÷View¸¦ ´©¸£°í ¿òÁ÷À϶§¸¶´Ù À̵¿°Å¸®¸¸Å °°ÀÌ ¿òÁ÷¿© ÁÝ´Ï´Ù.
private void setDraggable() {
rootView.setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
initialX = params.x;
initialY = params.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
return true;
case MotionEvent.ACTION_UP:
return true;
case MotionEvent.ACTION_MOVE:
params.x = initialX + (int) (event.getRawX() - initialTouchX);
params.y = initialY + (int) (event.getRawY() - initialTouchY);
if (rootView != null)
windowManager.updateViewLayout(rootView, params);
return true;
}
return false;
}
});
}
onStartCommand()¿¡¼ ¼¼ÆÃÇسõÀ½ Æ˾÷View¸¦ WindowManager¿¡ Ãß°¡ÇØÁÝ´Ï´Ù.
³Ñ°Ü¹ÞÀº ÀüȹøÈ£ Á¤º¸¸¦ °¡Á®¿Í¼ Æ˾÷ViewÀÇ TextView¿¡µµ ¼¼ÆÃÇØÁÝ´Ï´Ù.
onStartCommand()¿¡¼ START_REDELIVER_INTENT·Î ¼³Á¤Çϴ°æ¿ì Service°¡ °Á¦Á¾·á µÇ´õ¶óµµ ´Ù½Ã ½ÃÀÛÇØÁÖ°í ÀÌÀü¿¡ ³Ñ°Ü¹Þ¾Ò´ø intent¸¦ ±×´ë·Î ³Ñ°Ü¹ÞÀ» ¼ö ÀÖ½À´Ï´Ù.
¿©±â¼´Â STICKY·Î ÇØÁ־ Å©°Ô »ó°ü¾øÀ»°Í °°½À´Ï´Ù.
¸¸¾à intent°¡ nullÀΰæ¿ì¿£ Æ˾÷View¸¦ ¾ø¾ÖÁÝ´Ï´Ù.
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
windowManager.addView(rootView, params);
setExtra(intent);
if (!TextUtils.isEmpty(call_number)) {
tv_call_number.setText(call_number);
}
return START_REDELIVER_INTENT;
}
private void setExtra(Intent intent) {
if (intent == null) {
removePopup();
return;
}
call_number = intent.getStringExtra(EXTRA_CALL_NUMBER);
}
¼ºñ½º°¡ Á¾·áµÇ°Å³ª Æ˾÷ViewÀÇ X¹öÆ°ÀÌ ´¸®´Â°æ¿ì Æ˾÷View¸¦ ¾ø¾ÖÁÝ´Ï´Ù.
@Override
public void onDestroy() {
super.onDestroy();
removePopup();
}
@OnClick(R.id.btn_close)
public void removePopup() {
if (rootView != null && windowManager != null) windowManager.removeView(rootView);
}
±×·¸°Ô ¿Ï¼ºµÈ ȸéÀº ¾Æ·¡¿Í °°½À´Ï´Ù.
ÀüÈ°¡ °É·Á¿Ã°æ¿ì »ó´ë¹æÀÇ ÀüȹøÈ£¸¦ ³Ñ°Ü¹Þ¾Æ¼ Æ˾÷À¸·Î º¸¿©ÁÖ°Ô µË´Ï´Ù.
À̸¦ Àß È°¿ëÇؼ °¡Á®¿Â ÀüȹøÈ£¸¦ ¿î¿µÁßÀÎ ¼ºñ½ºÀÇ ¼¹ö¿¡ ¿äûÇؼ °¢Á¾ Á¤º¸¸¦ °¡Á®¿À´Â ±â´ÉÀ» ¸¸µé ¼öµµ ÀÖ½À´Ï´Ù.
¿©·¯°¡Áö ÀÀ¿ëµÈ ¹æ½ÄÀ¸·Î »ç¿ëÀÚ¿¡°Ô ÀǹÌÀÖ´Â Á¤º¸¸¦ ³ëÃâÇØÁÖ±æ ¹Ù¶ø´Ï´Ù.
ÀÌ°ÍÀú°Í ´Ù ±ÍÂúÀ¸½ÅºÐµéÀ» À§ÇØ Github¿¡ ÇÁ·ÎÁ§Æ®¸¦ ¿Ã·ÁµÎ¾ú½À´Ï´Ù.
Github¿¡¼ ´Ù¿î¹ÞÀ¸¼Å¼ Å×½ºÆ®ÇÁ·ÎÁ§Æ® ½ÇÇàÇغ¸¼Åµµ ÁÁ½À´Ï´Ù.
(³»¿ëÀÌ À¯¿ëÇϼ̴ٸé Github ¿À¸¥ÂÊÀ§ÀÇ [Star]¹öÆ°À» ´·¯ÁÖ½Ã¸é °¨»çÇÏ°Ú½À´Ï´Ù
Àú¿¡°Ô´Â º°Ç³¼± Áֽô ȿ°ú°¡ ÀÖ¾î¿ä!)
Ãâó: https://gun0912.tistory.com/46 [¹Ú»ó±ÇÀÇ »ðÁúºí·Î±×]