4

私は 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);
}

アプリを再起動するには、AsyncTaskRestartTask という呼び出しを行う直前に起動します。このコードはプラグイン内にあるため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);

これは、 PhoneGAPMainActivityから派生したメイン クラスであり、拡張されていますDroidGap

FLAG_ACTIVITY_CLEAR_TOP と FLAG_ACTIVITY_SINGLE_TOP を設定することはまさに人々がここで言っていることであり、アクティビティを「再アクティブ化」する場合はここで設定する必要があります。つまり、アクティビティが現在インスタンス化されているタスクが新しいタスクを作成する代わりに使用され、アクティビティが新しいアクティビティ インスタンスを作成する代わりに、実行中の状態で再利用されます。onNewIntentOS によってインテントが配信されると、「古い」アクティビティが呼び出されます。

ただし、電話がアクティブになっても何も起こらずMainActivity、いずれかの電話で電話を切るまで、インテントが に配信されていないようです。変。

フラグを include に変更するとFLAG_ACTIVITY_CLEAR_TOP、アプリ タスクまたはメイン アクティビティのいずれかが再開されます。ただし、これは PhoneGAP であるため、どちらもアプリの再起動に対応しており、これは私が望んでいたことではありません。また、フォーカスを与えられた別のタスクで、アプリのまったく新しいインスタンスを Android で起動させることもできます。

ただし、Android をメイン アクティビティにフォーカスさせることはできません。私は何を間違っていますか?

ありがとう!

4

1 に答える 1

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();
    }
}
于 2012-05-07T13:04:41.130 に答える