ACTION_VIEWまたはACTION_EDITでインテントを受け取ることで別のアプリから起動できるアプリを書いています。たとえば、電子メールの添付ファイルを表示して開くことができます。問題は、ホーム ボタンをクリックして、使用していたメール アプリの起動アイコンをもう一度クリックすると、アクティビティが強制終了され、ユーザーが行った編集が失われることです。私がしたいことは、ユーザーがホームボタンをクリックすると、アクティビティが再親化され、ユーザーがアプリの起動アイコンをクリックしたときに再開されるようにすることです。manifest.xml で android:allowTaskReparenting="true" を設定しようとしましたが、これは機能しません。まったく効果がない場合もあれば、アクティビティが起動アイコンに移動しても、メール アプリのアイコンをもう一度クリックすると強制終了される場合があります。allowTaskReparenting に関するドキュメントは非常に曖昧です。プロパティの意味は次のとおりです。
「アクティビティが、それを開始したタスクからアフィニティを持つタスクに移動 できるかどうか。」</p>
ここでできるという言葉はどういう意味ですか?私が欲しいのは、アクティビティが移動する (そしてそこにとどまる) という保証です。これを達成する方法はありますか?
助けていただける方、よろしくお願いします。
編集
以下のコメントに応えて、私が直面している問題を示す赤ちゃんバージョンをまとめました。別のアプリでファイル (電子メールの添付ファイルなど) をクリックして EditFileActivity を開始すると、そのファイルを編集できます。ただし、ホーム アイコンをクリックしてからメール アプリ アイコンをもう一度クリックすると、ファイルに加えた変更が失われます。ユーザーが明示的にクリックして「はい」または「いいえ」と言った場合にのみ、Android システムに EditFileActivity のインスタンスを忘れさせたいと思います。理想的には、EditFileActivity のすべてのインスタンスをアプリの起動アイコンに積み上げたいと考えています。singleTask または singleInstance を使用して、開いているすべてのファイルをタブに表示する何らかのアクティビティを作成することで、これに似たものを実装できますが、Android システム自体に助けてもらうことができれば、はるかに簡単になります。
これは、問題を示す完全なプロジェクトです。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.Example"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="11"/>
<application
android:label="Example"
android:icon="@drawable/ic_launcher">
<activity
android:name=".LaunchActivity"
android:label="LaunchActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".EditFileActivity"
android:label="EditFileActivity"
android:screenOrientation="portrait">
<!-- This is just an example. I wouldn't use this intent filter in a real app! -->
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<action android:name="android.intent.action.EDIT"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="file"/>
<data android:scheme="content"/>
<data android:mimeType="*/*"/>
<data android:host="*"/>
</intent-filter>
</activity>
</application>
</manifest>`
起動アクティビティ:
public class LaunchActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView textView = new TextView(this);
textView.setText("This is the activity you see when you click on the application's launch icon. It does absolutely nothing.");
textView.setTextSize(18);
setContentView(textView);
}
}
編集ファイル アクティビティ:
public class EditFileActivity extends Activity {
// This String represents the contents of the file.
// In a "real" app the String would be initialised by reading the data from the Intent that started the activity.
// However, for the purposes of this example, the initial value is "Default".
private String fileContents = "Default";
private boolean editsMade = false;
private TextView textView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
textView = new TextView(this);
textView.setText(fileContents);
textView.setTextSize(18);
textView.setPadding(10, 10, 10, 10);
setContentView(textView);
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
makeEdits();
}
});
}
@Override
public void onBackPressed() {
if (editsMade) {
savePrompt();
} else {
finish();
}
}
private void savePrompt() {
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == Dialog.BUTTON_POSITIVE) {
// Here is where I would save the edited file.
Toast.makeText(EditFileActivity.this, "File saved", Toast.LENGTH_LONG).show();
}
finish();
}
};
new AlertDialog.Builder(this)
.setTitle("Close File")
.setMessage("Do you want to save the changes you made?")
.setPositiveButton("Yes", listener)
.setNegativeButton("No", listener)
.show();
}
private void makeEdits() {
final EditText editText = new EditText(this);
editText.setText(fileContents);
new AlertDialog.Builder(this)
.setTitle("Edit File")
.setView(editText)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
Editable editable = editText.getText();
assert editable != null;
String newContents = editable.toString();
if (!fileContents.equals(newContents)) {
editsMade = true;
fileContents = newContents;
textView.setText(fileContents);
}
}
})
.setNegativeButton("Cancel", null)
.show();
}
}
2014 年 10 月 12 日更新
発生した問題は、インテント フラグ FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET の使用が原因でした。幸いなことに、API レベル 21 の時点で、Google はこのフラグを廃止しました。