안드로이드에서 서비스가 종료되지 않고 ANR이 발생합니다.

조회수 2241회

제가 애플리케이션 메인 액티비티가 onDestroy를 통해서 종료되면 Watcher라는 서비스가 startService를 통해 실행되도록 만들었습니다. 이 서비스에는 다음 코드와 같은 블루투스 연결 코드와 무한 루프가 존재합니다. 앱에도 서비스와 같이 블루투스를 연결하고 데이터를 받아오는 코드가 있습니다. 그런데 이 서비스를 실행하지 않을 때에는 괜찮은데, 서비스가 백그라운드에서 실행되는 동안 앱을 실행하면 하얀 화면만 뜨고 ANR이 발생합니다. 앱의 onCreate의 첫번째 줄에 stopService 명령을 작성했음에도 불구하고 서비스가 종료되지 않고 ANR이 발생합니다. 어떻게 해야 앱이 실행될 때 서비스를 종료시킬 수 있습니까?

//서비스 일부 코드입니다
public int onStartCommand(Intent intent, int flags, int startId) {
        //region 블루트스 연결
        bt = intent.getStringExtra("command");
        Log.d("bt", bt);
        try{
            Log.i("bt", "연결을 시작합니다! 연결할 값은 " + bt + " 입니다");
            if(mSocket == null || !isBtConnected){
                mBluetooth = BluetoothAdapter.getDefaultAdapter();
                BluetoothDevice btDev = mBluetooth.getRemoteDevice(bt);
                mSocket = btDev.createInsecureRfcommSocketToServiceRecord(mUUID);
                BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
                mSocket.connect();
                Toast.makeText(getApplicationContext(), "커넥트 성공", Toast.LENGTH_LONG).show();
                Log.i("bt", "성공");
            }
        }

        catch(IOException e){
            // FIXME: 2017-08-26 블루투스 연결이 실패했을 때 다이얼로그를 띄웁니다.
            Toast.makeText(getApplicationContext(), "ERR004, 블루투스 연결에 실패하였습니다.", Toast.LENGTH_LONG).show();
            final AlertDialog.Builder builder = new AlertDialog.Builder(this, AlertDialog.THEME_HOLO_LIGHT);
            builder.setTitle("설정을 시작하시겠습니까?")
                    .setMessage(("블루투스 연결을 성공적으로 해내지 못했습니다. 앱을 종료하고 나중에 다시 작동시킬 것인지," +
                            "아니면 지금 연결 설정을 다시 할 것인지 선택해 주세요. " +
                            "앱을 종료하면 다시 앱을 켤 떄까지 알림을 받지 못합니다."))
                    .setNegativeButton("설정", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            Intent settingIntent = new Intent(getApplicationContext(), SettingActivity.class);
                            startActivity(settingIntent);
                        }
                    })
                    .setPositiveButton("앱 종료", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            // TODO: 2017-08-27

                        }
                    }).show();
        }
        /////////////
        //endregion
        for(;;){
                receiveNotify();
                if(false){
                break;
            }

        }

        return super.onStartCommand(intent, flags, startId);
    }

  • (•́ ✖ •̀)
    알 수 없는 사용자
  • 서비스에서 AlertDialog 가 띄워지나요? 저거 에러 안나나요? 그리고 앱을 실행할 때 서비스를 종료하려는 접근 방법도 조금 생각을 달리 해야하지 않을까 싶습니다 알 수 없는 사용자 2017.9.8 17:43

1 답변

  • 안드로이드의 서비스는 메인(기본) 스레드에서 실행되는 컴포넌트입니다. 따라서 이 곳에서 무한루프를 실행하면 ANR이 발생할 수 밖에 없습니다. 그리고 stopService()를 호출하더라도 해당 루프에 의해 메인 스레드가 점유되고 있는 상태에서는 stopService() 또한 동작하지 않습니다.

    대안으로 인텐트 서비스(IntentService)를 사용하시거나 기존의 코드에서 새로운 스레드를 생성해 메인 스레드를 블럭 시키지 않도록 코드를 작성하세요. 작업이 완료되면 반드시 루프가 종료되는 처리를 넣으시기 바랍니다.

    인텐트 서비스와 관련된 설명 및 샘플 코드는 다음 링크를 참고하세요.

    • (•́ ✖ •̀)
      알 수 없는 사용자

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)