以编程方式进行调用后,我的Android应用程序崩溃了

时间:2010-05-04 05:02:58

标签: java android

标题解释了所有...我在我的应用程序中有这段代码:

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

它会拨打电话,但一旦通话结束,我的应用程序就会崩溃。一旦通话结束,我想回到我的应用程序,但我读了this post,似乎不可能。那么......无论如何,至少暂停我的应用程序并在通话结束后恢复它?

修改

感谢我收到的两个答案,我觉得我真的很接近我的目标......我已经完成了你们建议的一些事情。但是,也许我没有解释应用程序的一些细节...我正在开发谁想成为Millonarie 游戏,所以我需要实现调用(我不知道它是怎么称的在美国或其他国家,但在这里我们称之为“打电话给朋友”。)

无论如何......我对这个应用程序做了太多更改,现在它没有崩溃。但是,一旦调用结束,我绘制UI的Canvas就不显示了。

我有一个SurfaceView来保存用户界面。对于SurfaceView,我创建了一个用于刷新UI的线程......这基本上就是线程的作用:

@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类启动线程:

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

在我开始实施电话呼叫之前,这很好用。这里的问题是,一旦调用结束并再次执行start方法,该方法抛出IllegalThreadStateException,因为该线程已经启动。我尝试使用一些'技术'来暂停UI线程,但我无法解决这个问题。我尝试过这样的事情:

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

但那没用。我也尝试了其他一些“技巧”,例如使用sleep(50);代替wait();,但它也不起作用。

根据我提供的所有信息......你能给我什么建议?

3 个答案:

答案 0 :(得分:5)

可以使用android.telephony.PhoneStateListener

首先,我们需要处理应用程序的清单:

我们需要获得拨打电话的权限(duh!)以及观看电话状态的权限。后者是必需的,因此app也可以对呼叫的结束作出反应。因此,我们将这些行添加到应用程序清单中:

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

此外,我们不希望Android在调用结束时启动我们活动的其他实例,因此我们将活动的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事件并再次启动我们的活动,以便在调用结束后我们回到我们离开它的应用程序中。然后它会自行取消注册,因此每次用户结束不是由我们自己的活动发起的呼叫时,我们的活动都不会重新启动。

但是,当使用TelephonyManager注册CALL_STATE事件时,Android会立即触发当前状态的通知 - 因此我们的侦听器会在呼叫开始之前被触发。因此,我们的侦听器实现首先等待直到拨出呼叫(CALL_STATE_OFFHOOK),并且只有在发生后才会对CALL_STATE_IDLE通知做出反应。

HTH!

答案 1 :(得分:5)

这里的问题是你用来启动线程的地方。一旦你开始一个新的电话,你的主要活动将被暂停,并且表面视图将被销毁。虽然,该线程将继续运行。因此,一旦您的应用程序取回控件,将再次创建曲面并调用start方法。这会导致IllegalThreadStateException。

这里的方法是从SurfaceView类中操纵线程。这将使您能够控制主活动中的线程,并且您将能够决定何时开始或暂停您的线程。

看一下这个例子:http://code.google.com/p/apps-for-android/source/browse/trunk/SpriteMethodTest/src/com/android/spritemethodtest/

答案 2 :(得分:1)

至于崩溃 - 请发布日志并将调试器放在Start / 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中使用该功能的应用程序中使用它的示例