티스토리 뷰

 

  • 서비스
  • 프로드캐스트 리시버
  • 콘텐트 프로바이더

 

서비스

서비스는 일반적으로 화면 없이 동작하는 프로그램이다.

데몬, 백그라운드 프로세스 라고 칭하기도 한다.

서비스가 데몬으로 동작하는 과정을 살펴보자.

서비스가 이루어지는 과정

서비스 요청이 시작되면 onCreate(), onStartCommand() 가 동작한다.

서비스 중지 요청을 받으면 onDestroy() 가 동작하고 서비스가 종료된다.

 

백그라운드에서 음악을 실행해주는 어플을 만들어보자.

서비스를 사용하기 위해서는 Service 클래스의 상속을 받는 클래스를 만들어야 한다.

MusicService <- Service 그 후 Service 클래스의 메소드를 오버라이딩 한다.

onCreate(), onStartCommnad(), onDestroy() 메소드 오버라이딩

 

해당 서비스 과정이 이루어지는 과정을 로그로 담기기 위한 코드를 작성.

public class MusicService extends Service {

     MediaPlayer mp;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        android.util.Log.i("서비스 테스트", "onCreate()");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        android.util.Log.i("서비스 테스트", "onStartCommand()");
        mp = MediaPlayer.create(this, R.raw.song);
        mp.setLooping(true); // 반복 설정 => true
        mp.start();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        android.util.Log.i("서비스 테스트", "onDestroy()");
        mp.stop();
        super.onDestroy();
    }
}

이후 메인 java 코드를 작성한다.

public class MainActivity extends AppCompatActivity {

    Intent intent;
    Button btnStart, btnStop;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setTitle("서비스 테스트 예제");

        intent = new Intent(this, MusicService.class);
        btnStart = (Button) findViewById(R.id.btnStart);
        btnStop = (Button) findViewById(R.id.btnStop);

        btnStart.setOnClickListener(new View.OnClickListener(){
            public void onClick(View v) {
                startService(intent);
                android.util.Log.i("서비스 테스트 시작", "startService()");
            }
        });
        btnStop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                stopService(intent);
                android.util.Log.i("서비스 테스트 종료", "stopService()");
            }
        });
    }
}

코드보기!

MusicService.class 파일은 인텐트로 생성한다. =>intent = new intent(this, MusicService.class);

서비스가 시작하고 끝내는 것을 intent를 이용하여 구현한다.

startService(intent) / stopService(intent)

 

※ 서비스 xml 등록!

 : 서비스도 액티비티와 마찬가지로 AndroidManifest.xml에 등록해야 사용할 수 있다.

        <service android:name=".MusicService">
            <intent-filter>
                <action android:name="com.example.a14_1"/>
            </intent-filter>
        </service>

브로드캐스트 리시버

브로드캐스트 리시버는 안드로이드에서 발생하는 여러 변화에 대하여 신호(broadcast)를 보낸다.

여러 변화에는 배터리방전, 메시지 도착, 네트워크 환경 등등 이 있다. 이러한 변화에 대하여 신호(broadcast)를 받아 처리하는 것이 브로드캐스트 리시버이다.

 

브로드캐스트 리시버의 대표적인 응용이 배터리 상태 확인이다.

배터리 상태 확인 액션

액션 설명
ACTION_BATTERY_CHANGED 배터리의 상태가 변경될 때
ACTION_BATTERY_LOW 배터리가 거의 방전되었을 때
ACTION_BATTERY_OKAY 배터리가 방전 상태에서 정상으로 돌아올 때

 

 

배터리 상태가 변할 때 충전 상태 이미지와 배터리 상태를 출력하는 앱을 만들어보자

- 인텐트의 엑스트라에서 배터리의 잔량을 추출한 후 그에 따라 잔량을 표시하고 배터리 이미지를 변경

- 인텐트의 엑스트라에서 배터리의 전원 연결 상태를 출출하여 표시

public class MainActivity extends AppCompatActivity {
    ImageView ivBattery;
    EditText edtBattery;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setTitle("배터리 상태 체크");

        ivBattery = (ImageView)findViewById(R.id.ivBattery);
        edtBattery = (EditText)findViewById(R.id.edtBattery);
    }

    BroadcastReceiver br = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if(action.equals(Intent.ACTION_BATTERY_CHANGED)){
                int remain = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
                edtBattery.setText("현재 충전량 : " + remain + " %\n");

                if(remain >= 90) ivBattery.setImageResource(R.drawable.battery_90);
                else if (remain >= 70) ivBattery.setImageResource(R.drawable.battery_70);
                else if (remain >= 50) ivBattery.setImageResource(R.drawable.battery_50);
                else if (remain >= 30) ivBattery.setImageResource(R.drawable.battery_30);
                else if (remain >= 10) ivBattery.setImageResource(R.drawable.battery_10);

                int plug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
                switch (plug){
                    case 0 :
                        edtBattery.append("전원 연결 : 안됨");
                        break;
                    case BatteryManager.BATTERY_PLUGGED_AC:
                        edtBattery.append("전원 연결 : 어댑터 연결됨");
                        break;
                    case BatteryManager.BATTERY_PLUGGED_USB :
                        edtBattery.append("전원 연결 : USB연결됨");
                        break;
                }
            }
        }
    };

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(br);
    }

    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter iFilter = new IntentFilter();
        iFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        registerReceiver(br, iFilter);
    }
}

코드보기

 : BroadReceive 객체를 생성하고 onReceive() 메소드에서 인텐트의 액션이 베터리가 변경된 신호인 ACTION_BATTERY_CHANGED 인 경우가 발생했을 때를 코딩하였다.

배터리가 변하면 onReceive() 메소드가 자동으로 호출.

intent 필터 객체를 생성 => ACTION_BATTERY_CHANGED 액션을 추가.

intent 필터를 생성한 BR에 등록한다.

 

콘텐트 프로바이더(Content Provider, CP)

안드로이드는 보안상 앱에서 사용하는 데이터를 외부에서 접근할 수 없다.

데이터를 외부 앱에서 사용하게 하려면 콘텐트 프로바이더를 만들어서 외부에 제공해야한다.

콘텐트 프로바이더가 제공하는 데이터에 접근하기 위해서는 해당 주소가 있어야 하는데 이를 

URI(uniform resource identifier)라고 한다.

 

안드로이드는 자체에서 제공하는 콘텐트 프로바이더를 사용하는 경우가 있다.

콘텐트 프로바이더를 사용하는 과정은 데이터와 관련된 URI 제공하고 사용자는 getContentResolver() 메소드를 이용하여 ContentResolver 클래스를 얻은 후 접근할 수 있다.

안드로이드에서 제공하는 콘텐트 프로바이더

## 통화기록을 가져오는 예제

 

우선, 통화 기록에 접근하기 위해서는 AndroidManifest.xml의 <application> 위에 접근 권한을 주는 코드를 작성한다.

<uses-permission android:name="android.permssion.READ_CALL_LOG>

설명은 코드와 함께~

public class MainActivity extends AppCompatActivity {

    Button btnCall;
    EditText edtCall;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ActivityCompat.requestPermissions(this, new String[] {
                Manifest.permission.READ_CALL_LOG}, MODE_PRIVATE);  // 직접 퍼미션을 허용하는 코드가 필요

        btnCall = (Button)findViewById(R.id.btnCall);
        edtCall = (EditText)findViewById(R.id.edtCall);

        btnCall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                edtCall.setText(getCallHistory()); // getCallHistory 호출 => 결과를 edtCall 에 출력
            }
        });
    }
    public String getCallHistory(){     // 통화 기록의 내용을 검색해서 기록을 문자열로 만들어 반환하는 함수
        String[] callSet = new String[] { // 퉁화기록을 저장할 문자열 배열을 만듦
                CallLog.Calls.DATE, CallLog.Calls.TYPE, CallLog.Calls.NUMBER, CallLog.Calls.DURATION
        };
        Cursor c = getContentResolver().query(CallLog.Calls.CONTENT_URI, callSet, null, null,null);
        if(c == null) return "통화기록 없음"; // 통화기록이 없으면 ==> 종료

        StringBuffer callBuff = new StringBuffer(); // 통화 기록의 문자열을 저장할 StringBuffer 변수를 준비
        callBuff.append("\n날짜 : 구분 : 전화번호 : 통화시간 \n\n");
        c.moveToFirst(); // 통화기록의 처음 행으로 이동
        do{ // 통화기록의 마지막까지 반복
            long callDate = c.getLong(0);
            SimpleDateFormat datePattern = new SimpleDateFormat("yyyy-MM--dd");
            String date_str = datePattern.format(new Date(callDate));
            callBuff.append(date_str + ":"); // 처음 필드를 가져와 날짜 형식으로 버퍼에 저장
            if(c.getInt(1) == CallLog.Calls.INCOMING_TYPE) callBuff.append("착신");
            else callBuff.append("발신"); // 첫 번째 필드 데이터(착신/발신)를 가져와 저장
            callBuff.append(c.getString(2) + ":"); // 두 번째 필드(전화번호)의 내용을 버퍼에 저장
            callBuff.append(c.getString(3) + "초\n"); // 세 번째 필드(통화시간)의 내용을 버퍼에 저장
        }while(c.moveToNext());

        c.close();
        return callBuff.toString(); // 저장한 모든 정보를 반환.
    }
}

(출처 : Android Studio를 활용한 안드로이드 프로그래밍)

20000 갑니다.

 

 

'학교공부 > 안드로이드' 카테고리의 다른 글

안드로이드(1)  (0) 2021.10.15
chaper 10 (액티비티와 인텐트)  (0) 2021.04.22
chapter 8 (파일처리)  (0) 2021.04.21
chapter 7 (메뉴와 대화상자)  (0) 2021.04.21
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함