2010-05-04 3 views
1

충돌 :프로그래밍 방식으로 전화를 한 후, 내 안드로이드 응용 프로그램 제목은 내 응용 프로그램에서이 코드 조각을 가지고 ... 모든 설명

String url = createTelUrl("3112007315"); 
Intent intent = new Intent(Intent.ACTION_CALL); 
intent.setData(Uri.parse(url)); 
context.startActivity(intent); 

그것은 전화를 걸 않지만, 통화가 끝나면 한 번, 내 응용 프로그램이 충돌합니다. 전화가 끝나면 내 신청서로 돌아가고 싶지만, this post을 읽으면 가능하지 않은 것 같습니다. 그럼 ... 어쨌든 적어도 내 응용 프로그램을 일시 중지하고 통화가 끝나면 다시 시작할 수 있습니까?

는 편집 : 내가받은 두 답변을

덕분에, 나는 내 목표에 정말 가까이있어 기분이 ... 나는 이미 너희들이 제시 한 몇 가지 일을했다. 하지만, 어쩌면 내가 응용 프로그램의 일부 내용을 설명하지 않았다 ... 나는 개발 중이다 Millonarie가되고 싶은 사람 게임, 그래서 나는 전화를 구현할 필요가있다. (나는 그것이 미국이나 다른 나라들에서 어떻게 불려지는지 모른다. 그러나 여기에서는 이것을 "친구에게 전화"라고 부릅니다).

어쨌든 ... 나는이 응용 프로그램에 너무 많은 변경을했는데 지금은 충돌하지 않습니다. 그러나 UI가 그려진 Canvas는 호출자가 종료되면 표시되지 않습니다.

나는 UI가 들어있는 SurfaceView입니다. 호출이 나는 검은 색 화면을 얻을 종료되면,

@Override 
public void run() { 
    Canvas c; 
    while (_run) { 
     c = null; 
     try { 
      c = _surfaceHolder.lockCanvas(null); 
      // Check if should wait 
      synchronized (_surfaceHolder) { 
       _panel.onDraw(c); 
      } 
     } finally { 
      // do this in a finally so that if an exception is thrown 
      // during the above, we don't leave the Surface in an 
      // inconsistent state 
      if (c != null) { 
       _surfaceHolder.unlockCanvasAndPost(c); 
      } 
     } 
    } 
} 

그러나 : 그 SurfaceView를 들어 내가 UI를 갱신하기위한 것입니다 스레드를 생성 ...이 스레드가 무엇을 기본적으로. 표면이 있습니다 (아직 터치 이벤트를받을 수 있기 때문에 그것을 압니다). 그러나 아무것도 보이지 않습니다. 이것은 좋은 일

public void surfaceCreated(SurfaceHolder holder) { 
    hilo.setRunning(true); 
    try{ 
     hilo.start(); 
    }catch(IllegalThreadStateException ite){ 
     Log.e("wwtbam", "god dammed"); 
    } 
} 

내가 전화 통화를 구현하기 시작하기 전에 : 계정에 걸릴 수있는 또 다른 것은 내가 SurfaceView 클래스에서 스레드를 시작하고 방법이다. 여기서 문제는 일단 호출이 종료되고 스레드가 이미 시작되었으므로 IllegalThreadStateException을 던지는 start 메소드를 다시 실행한다는 것입니다. 호출하는 동안 UI 스레드를 일시 중지하기 위해 일부 '기술'을 사용해 보았지만이 문제를 해결할 수 없었습니다. 나는 다음과 같은 일을 시도했다 :

// this in the UI thread class 
if(haveToWait) 
    wait(); 
.... 
// this in the surface view class 
if(callEnded) 
    hilo.notify(); 

그러나 그것은 작동하지 않았다. 또한 wait(); 대신 sleep(50);을 사용하는 것과 같은 다른 '트릭'을 시도했지만 작동하지 않습니다.

내가 제공 한 모든 정보를 통해 ... 내게 어떤 제안을 할 수 있습니까?

답변

5

문제는 여기에 당신이 스레드를 시작하는 데 사용하는 장소입니다. 새 통화를 시작하면 주요 활동이 일시 중지되고 표면보기가 삭제됩니다. , 스레드가 계속 실행됩니다. 따라서 앱이 컨트롤을 다시 가져 오면 서페이스가 다시 만들어지고 시작 메서드가 호출됩니다. 이로 인해 IllegalThreadStateException이 발생합니다.

여기하는 방법은 서피스 뷰 SurfaceView 클래스에서 스레드를 조작하는 것입니다. 이렇게하면 주 활동에서 스레드를 제어 할 수 있으며 스레드를 시작하거나 일시 중지 할시기를 결정할 수 있습니다.

이 예를 살펴 보자 http://code.google.com/p/apps-for-android/source/browse/trunk/SpriteMethodTest/src/com/android/spritemethodtest/

1

크래시와 관련하여 로그를 게시하고 디버거를 OnStart/onResume에 배치하여 충돌하는 이유를 확인하십시오. 잘못된 장소에서 무언가가 초기화 될 수 있으며 nullpointer처럼 간단 할 수도 있습니다. 통화 종료 건에 관해서는

-이 시도 적이하지만 난, 수신기를 등록 http://developer.android.com/reference/android/telephony/TelephonyManager.html#ACTION_PHONE_STATE_CHANGED 전화의 상태를 평가하고 당신이해야 할 일을 잡으려고 것입니다.

또한 여기에 대한 추가 정보를 원하시면 http://developer.android.com/reference/android/telephony/ http://developer.android.com/reference/android/telephony/PhoneStateListener.html

을가 그리고 마지막으로 당신은 source.android에서 해당 기능을 사용할 수있는 응용 프로그램에서 그것을 사용하는 방법의 예를 찾을 수 있습니다.COM은

+0

감사합니다 ... 나는 새로운 정보를 포함하여 게시물을 편집했다. 더 정보를 제공하도록 답장을 보내 – Cristian

5

이것은 android.telephony.PhoneStateListener를 사용하여 가능하다.

첫째, 우리는 응용 프로그램의 매니페스트 돌봐해야합니다

우리는 통화를 (! 대만족)뿐만 아니라 휴대 전화 상태를 볼 수있는 권한을 권한이 필요합니다. 후자는 앱이 통화 종료에 반응 할 수 있도록 필요합니다. 또한

<uses-permission android:name="android.permission.CALL_PHONE" /> 
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> 

, 우리는 호출이 종료 될 때 안드로이드는 우리의 활동의 다른 인스턴스를 시작하고 싶지 않아, 그래서 우리는 활동의 launchMode 속성을 ": 그래서 우리는 밖으로 응용 프로그램 매니페스트에 다음 줄을 추가 singleInstance ".

<activity android:name=".CallTest" android:label="Calling Test" 
     android:launchMode="singleInstance" /> 

가 매니페스트에 모든 것을 준비하는 데, 우리가 지금 전화를 만드는 활동을 볼 수 있습니다 :

질문의 코드에 비해
public class CallTest extends Activity { 
    PhoneStateListener mListener; 
    TelephonyManager mTelMgr; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     mListener = new CallEndedListener(); 
     mTelMgr = (TelephonyManager) this.getSystemService(TELEPHONY_SERVICE); 
    } 

    public void makecall(View v) { 
     // Register our listener to be notified of the beginning 
     // and ending of calls 
     mTelMgr.listen(mListener, PhoneStateListener.LISTEN_CALL_STATE); 

     // Start the call 
     Intent call = new Intent(Intent.ACTION_CALL); 
     call.setData(Uri.parse("tel:12345")); 
     startActivity(call); 
    } 

    class CallEndedListener extends PhoneStateListener { 
     boolean called = false; 

     @Override 
     public void onCallStateChanged(int state, String incomingNumber) { 
      super.onCallStateChanged(state, incomingNumber); 

      // Don't fire before the call was made 
      if (state == TelephonyManager.CALL_STATE_OFFHOOK) 
       called = true; 

      // Call has ended -- now bring the activity back to front 
      if (called && state == TelephonyManager.CALL_STATE_IDLE) { 
       called = false; 
       mTelMgr.listen(this, PhoneStateListener.LISTEN_NONE); 
       startActivity(new Intent(CallTest.this, CallTest.class)); 
      } 
     } 
    } 
} 

makecall 방법의 유일한 새로운 것은, 실제로 전화를 걸기 바로 전에 PhoneStateListener 구현이 추가되었습니다. 이 수신기는 발신 전화가 걸려 올 때, 걸려 오는 전화가 울릴 때 또는 통화가 끝날 때 Android에 의해 알립니다.

우리의 구현은 후자 CALL_STATE_IDLE 이벤트를 대기하고 통화가 종료 된 후 것을 우리가 우리가 그것을 왼쪽 우리의 응용 프로그램에있어, 그래서 다시 우리의 활동을 시작한다. 그런 다음 등록이 취소되므로 사용자가 자신의 활동으로 시작하지 않은 통화를 종료 할 때마다 Google의 활동이 다시 시작되지 않습니다.

그러나 CALL_STATE-events를 TelephonyManager으로 등록하면 Android가 즉시 현재 상태 알림을 실행하므로 호출이 시작되기 전에 수신자가 트리거됩니다. 발신 통화가 시작 (CALL_STATE_OFFHOOK) 및 해당 후 CALL_STATE_IDLE 통지에 반응하여 일어난 때까지 따라서 우리의 리스너 구현은 첫째 기다립니다.

HTH!

+0

감사합니다 ... 난 게시물을 편집했습니다. – Cristian

관련 문제