我正在构建一个基于PhoneGAP的应用程序,在那里我需要拨打电话,然后在说5秒后返回我的应用程序。
关于拨打电话的部分可以正常工作。要通过呼叫而不仅仅是拨号盘打开Android,进行呼叫的代码将放在com.phonegap.api.Plugin中,看起来像
private void callNumber(String phoneNumber){
Uri calling = Uri.parse("tel:" + phoneNumber);
Intent callIntent = new Intent(Intent.ACTION_CALL, calling);
this.ctx.startActivity(callIntent);
}
要重新启动应用程序,我在调用RestartTask之前启动AsyncTask
。因为这段代码存在于插件中,所以我必须使用Activity.runOnUiThread
来启动RestartTask,但除此之外没什么特别之处。
在RestartTask中,只实现了doInBackground
方法并且它完成了所有方法,它正在休眠5秒钟,然后运行以下意图:
Intent restartIntent = new Intent(DialerPlugin.this.ctx.getBaseContext(), MainActivity.class);
restartIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
DialerPlugin.this.ctx.startActivity(restartIntent);
此处MainActivity
是来自PhoneGAP的派生主类,它扩展了DroidGap
。
设置FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_SINGLE_TOP正是人们所说的here和here,如果活动要“重新激活”,这意味着活动当前实例化的任务是使用而不是创建新任务,并且活动将与其运行状态一起重用,而不是创建新的活动实例。当操作系统提供意图时,“旧”活动将被调用onNewIntent
。
然而,当电话呼叫变为活动状态时,没有任何反应,似乎意图未传递到MainActivity
,直到我挂断其中一部电话。怪异。
如果我将标志更改为包含FLAG_ACTIVITY_CLEAR_TOP
,则重新启动应用任务或主要活动。但是,因为这是PhoneGAP,两者都对应于重新启动应用程序,这不是我想要的。我还可以在另一项任务中将Android启动作为我的应用程序的全新实例,这是重点。
但是我无法让Android重点关注我的主要活动。我做错了什么?
谢谢!
答案 0 :(得分:3)
经过多个小时的黑客攻击后,我设法解决了这个问题。 看来,一旦新的android任务获得控制权,这就是当使用内置拨号器进行呼叫时发生的事情,后台任务从任务开始,这使得调用也失去了开始新活动的特权,除非它正在开始一项新任务。
这意味着,就是AsyncTask是在调用之前从活动启动的,然后稍微睡一下以确保拨号器任务/活动是打开的,它必须启动一个新任务以获得后焦点。不能再次启动Cordova活动,因为这会有效地重启整个应用程序,因此解决方案是进行精简重启任务,立即完成。
在Cordova插件中,可以放置以下内部类:
protected class RestartTask extends AsyncTask<Void, Void, Void>{
protected RestartTask() { }
@Override
protected Void doInBackground(Void... unused){
try {
// pass time so the built-in dialer app can make the call
Thread.sleep(MyPlugin.restartDelay);
}
catch (InterruptedException localInterruptedException)
{
Log.d("MyPlugin", "RestartTask received an InterruptedException");
}
return null;
}
@Override
protected void onPostExecute(Void justEyeCandy){
super.onPostExecute(justEyeCandy);
// Start the RestartActivity in a new task. This will snap the phone out of the built-in dialer app, which
// has started in it's own task at this point in time. The RestartActivity gains control and finishes
// immediately, leading control back to the activity at the top of the stack in the
// app (where the user came from when making the call).
Intent restartIntent = new Intent(MyPlugin.this.ctx.getApplicationContext(), RestartActivity.class);
restartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MyPlugin.this.ctx.getApplicationContext().startActivity(restartIntent);
}
}
可以通过调用:
在插件中启动此AsyncTask
this.ctx.runOnUiThread(new Runnable(){
public void run(){
try {
RestartTask restartTask = new RestartTask();
restartTask.execute();
}
catch (Exception e) {
Log.d("MyPlugin", "Exploded when trying to start background task: " + e.getMessage());
}
}
});
AsyncTask在新任务中启动的类是:
public class RestartActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// the prototype RestartActivity there is a possibility that this will be the root activity of the app.
// If that is the case, this activity will boot the main activity of the app in a new task, before signing off.
// However, this is not the case for this app, as restarts are only used once a call diversion has taken place,
// form within the app.
if (isTaskRoot())
{
// Start the app before finishing
String packageName = this.getBaseContext().getPackageName();
Intent startAppIntent = this.getBaseContext().getPackageManager().getLaunchIntentForPackage(packageName);
startAppIntent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
startActivity(startAppIntent);
}
// Now finish, which will drop the user in to the activity that was at the top of the task stack
finish();
}
}