最近の画面

履歴画面(概要画面、最近のタスクリスト、最近使ったアプリ画面とも呼ばれます)は、最近アクセスしたアクティビティタスクをリストするシステムレベルの UI です。ユーザーは、リスト内を移動したり、再開するタスクを選択したり、スワイプしてリストからタスクを削除したりできます。

履歴画面は、Android 5.0(API レベル 21)で導入されたドキュメント中心のモデルを使用します。このモデルでは、異なるドキュメントを含む同じアクティビティの複数のインスタンスが、履歴画面にタスクとして表示されます。たとえば、Google ドライブには、複数の Google ドキュメントごとにタスクがあるとします。各ドキュメントは履歴画面にタスクとして表示されます。

2 つの Google ドライブ ドキュメントが別々のタスクとして表されている [履歴] 画面。

もう一つの一般的な例は、ユーザーがブラウザで [共有] > [Gmail] をタップした場合です。Gmail アプリの [作成] 画面が表示されます。その時点で [最近] ボタンをタップすると、Chrome と Gmail が別々のタスクとして実行されていることがわかります。

Chrome と Gmail が別々のタスクとして実行されている [履歴] 画面。

通常は、履歴画面でのタスクとアクティビティの表示方法をシステムに定義させることができます。この動作を変更する必要はありません。ただし、アプリは、履歴画面にアクティビティを表示する方法とタイミングを決定できます。

ActivityManager.AppTask クラスを使用するとタスクを管理できます。Intent クラスのアクティビティ フラグを使用すると、履歴画面でアクティビティが追加または削除されるタイミングを指定できます。また、<activity> 属性を使用すると、マニフェスト内で動作を設定できます。

履歴画面にタスクを追加する

Intent クラスのフラグを使用してタスクを追加すると、履歴画面でドキュメントを開くタイミングと方法をより細かく制御できます。<activity> 属性を使用する場合は、常に新しいタスクでドキュメントを開くか、ドキュメントで既存のタスクを再利用するかを選択できます。

インテント フラグを使用してタスクを追加する

アクティビティの新しいドキュメントを作成するときに、startActivity() メソッドを呼び出して、アクティビティを起動するインテントを渡します。論理ブレークを挿入してシステムがアクティビティを履歴画面の新しいタスクとして扱うには、アクティビティを起動する IntentaddFlags() メソッドで FLAG_ACTIVITY_NEW_DOCUMENT フラグを渡します。

新しいドキュメントの作成時に FLAG_ACTIVITY_MULTIPLE_TASK フラグを設定すると、システムは常にターゲット アクティビティをルートとする新しいタスクを作成します。この設定により、同じドキュメントを複数のタスクで開くことができます。次のコードは、メイン アクティビティがどのようにこれを行うかを示しています。

Kotlin

fun createNewDocument(view: View) {
    val newDocumentIntent = newDocumentIntent()
    if (useMultipleTasks) {
        newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
    }
    startActivity(newDocumentIntent)
}

private fun newDocumentIntent(): Intent =
        Intent(this, NewDocumentActivity::class.java).apply {
            addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT or
                    android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS)
            putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, documentCounter++)
        }

Java

public void createNewDocument(View view) {
      final Intent newDocumentIntent = newDocumentIntent();
      if (useMultipleTasks) {
          newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
      }
      startActivity(newDocumentIntent);
  }

  private Intent newDocumentIntent() {
      boolean useMultipleTasks = checkbox.isChecked();
      final Intent newDocumentIntent = new Intent(this, NewDocumentActivity.class);
      newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
      newDocumentIntent.putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, documentCounter++);
      return newDocumentIntent;
  }

}

メイン アクティビティが新しいアクティビティを起動すると、システムは既存のタスクを検索し、インテント コンポーネント名およびアクティビティのインテント データがインテント データと一致するものを探します。タスクが見つからない場合、またはインテントに FLAG_ACTIVITY_MULTIPLE_TASK フラグが含まれている場合は、アクティビティをルートとして新しいタスクが作成されます。

システムは、インテント コンポーネント名およびインテント データと一致するインテントのタスクを見つけると、そのタスクを前面に移動し、新しいインテントを onNewIntent() に渡します。次の例に示すように、新しいアクティビティがインテントを取得し、履歴画面に新しいドキュメントを作成します。

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_new_document)
    documentCount = intent
            .getIntExtra(DocumentCentricActivity.KEY_EXTRA_NEW_DOCUMENT_COUNTER, 0)
    documentCounterTextView = findViewById(R.id.hello_new_document_text_view)
    setDocumentCounterText(R.string.hello_new_document_counter)
}

override fun onNewIntent(newIntent: Intent) {
    super.onNewIntent(newIntent)
    /* If FLAG_ACTIVITY_MULTIPLE_TASK has not been used, this Activity
    will be reused. */
    setDocumentCounterText(R.string.reusing_document_counter)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_new_document);
    documentCount = getIntent()
            .getIntExtra(DocumentCentricActivity.KEY_EXTRA_NEW_DOCUMENT_COUNTER, 0);
    documentCounterTextView = (TextView) findViewById(
            R.id.hello_new_document_text_view);
    setDocumentCounterText(R.string.hello_new_document_counter);
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    /* If FLAG_ACTIVITY_MULTIPLE_TASK has not been used, this activity
    is reused to create a new document.
     */
    setDocumentCounterText(R.string.reusing_document_counter);
}

アクティビティ属性を使用してタスクを追加する

アクティビティは、<activity> 属性 android:documentLaunchMode を使用して、常に新しいタスクで起動することをマニフェストで指定することもできます。この属性には 4 つの値があり、ユーザーがアプリでドキュメントを開いたときに次のような効果をもたらします。

intoExisting
アクティビティがドキュメント用に既存のタスクを再利用します。これは、インテント フラグを使用してタスクを追加するセクションで説明しているように、FLAG_ACTIVITY_MULTIPLE_TASK フラグを設定せずに FLAG_ACTIVITY_NEW_DOCUMENT フラグを設定するのと同じです。
always
すでにドキュメントが開いている場合でも、アクティビティはドキュメント用に新しいタスクを作成します。この値の使用は、FLAG_ACTIVITY_NEW_DOCUMENT フラグと FLAG_ACTIVITY_MULTIPLE_TASK フラグを両方設定する場合と同じです。
none
アクティビティは、ドキュメント用に新しいタスクを作成しません。履歴画面では、アクティビティはデフォルトとして扱われます。アプリに対して 1 つのタスクが表示され、ユーザーが最後に呼び出したアクティビティから再開します。
never
アクティビティは、ドキュメント用に新しいタスクを作成しません。この値を設定すると、FLAG_ACTIVITY_NEW_DOCUMENT フラグと FLAG_ACTIVITY_MULTIPLE_TASK フラグの動作がオーバーライドされます。このいずれかがインテントに設定され、履歴画面にアプリのタスクが 1 つ表示されると、ユーザーが最後に呼び出したアクティビティから再開します。

タスクを削除する

デフォルトでは、ドキュメント タスクは、アクティビティが終了すると履歴画面から自動的に終了します。この動作は、ActivityManager.AppTask クラス、Intent フラグ、または <activity> 属性でオーバーライドできます。

<activity> 属性 android:excludeFromRecentstrue に設定することで、いつでも履歴画面からタスクを完全に除外できます。

アプリが履歴画面に含めることができるタスクの最大数を設定するには、<activity> 属性 android:maxRecents を整数値に設定します。タスクの最大数に達すると、最も長い間使われていないタスクが履歴画面に表示されなくなります。デフォルト値は 16、最大値は 50(メモリの少ないデバイスでは 25)です。1 未満の値は無効です。

AppTask クラスを使用してタスクを削除する

履歴画面に新しいタスクを作成するアクティビティでは、finishAndRemoveTask() メソッドを呼び出して、タスクを削除して関連するすべてのアクティビティを終了するタイミングを指定できます。

Kotlin

fun onRemoveFromOverview(view: View) {
    // It is good pratice to remove a document from the overview stack if not needed anymore.
    finishAndRemoveTask()
}

Java

public void onRemoveFromRecents(View view) {
    // The document is no longer needed; remove its task.
    finishAndRemoveTask();
}

完了したタスクを保持する

アクティビティが終了した場合でも、履歴画面にタスクを保持する場合は、アクティビティを起動するインテントの addFlags() メソッドで FLAG_ACTIVITY_RETAIN_IN_RECENTS フラグを渡します。

Kotlin

private fun newDocumentIntent() =
        Intent(this, NewDocumentActivity::class.java).apply {
            addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT or
                    android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS)
            putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, getAndIncrement())
        }

Java

private Intent newDocumentIntent() {
    final Intent newDocumentIntent = new Intent(this, NewDocumentActivity.class);
    newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
      android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
    newDocumentIntent.putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, getAndIncrement());
    return newDocumentIntent;
}

同じ効果を得るには、<activity> 属性 android:autoRemoveFromRecentsfalse に設定します。デフォルト値は、ドキュメント アクティビティの true、通常のアクティビティの false です。この属性を使用すると、FLAG_ACTIVITY_RETAIN_IN_RECENTS フラグがオーバーライドされます。

最近の URL の共有を有効にする(Google Pixel のみ)

Android 12 以降を搭載した Google Pixel デバイスでは、ユーザーが最近表示したウェブ コンテンツのリンクを履歴画面から直接共有できます。アプリでコンテンツにアクセスした後、ユーザーは [履歴] 画面までスワイプしてコンテンツを表示したアプリを見つけ、リンクボタンをタップして URL をコピーまたは共有できます。

最近表示したウェブ コンテンツを共有するためのリンクが表示されている [履歴] 画面。

次の例に示すように、どのアプリでも、ウェブ UI を提供し、onProvideAssistContent() をオーバーライドすることで、ユーザーの履歴のリンクを有効にできます。

Kotlin

class MainActivity : AppCompatActivity() {
    protected fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    fun onProvideAssistContent(outContent: AssistContent) {
        super.onProvideAssistContent(outContent)
        outContent.setWebUri(Uri.parse("https://example.com/myCurrentPage"))
    }
}

Java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public void onProvideAssistContent(AssistContent outContent) {
        super.onProvideAssistContent(outContent);

        outContent.setWebUri(Uri.parse("https://example.com/myCurrentPage"));
    }
}