1 /* 2 * Copyright 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.pump.activity; 18 19 import android.app.Activity; 20 import android.content.ActivityNotFoundException; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.os.Bundle; 24 import android.widget.Toast; 25 26 import androidx.annotation.NonNull; 27 import androidx.annotation.Nullable; 28 import androidx.annotation.UiThread; 29 30 import com.android.pump.util.Clog; 31 32 @UiThread 33 // This class needs to inherit from Activity in order for Theme.Translucent to be applied correctly. 34 public class ActivityStarterActivity extends /* NOT AppCompatActivity !!! */ Activity { 35 private static final String TAG = Clog.tag(ActivityStarterActivity.class); 36 37 private static final int REQUEST_CODE = 42; 38 private static final String EXTRA_INTENT = 39 "com.android.pump.activity.ActivityStarterActivity.EXTRA_INTENT"; 40 private static final String EXTRA_OPTIONS = 41 "com.android.pump.activity.ActivityStarterActivity.EXTRA_OPTIONS"; 42 43 private boolean mApplicationCrashed; 44 createStartIntent(@onNull Context context, @NonNull Intent intent, @Nullable Bundle options)45 public static @NonNull Intent createStartIntent(@NonNull Context context, 46 @NonNull Intent intent, @Nullable Bundle options) { 47 Intent wrapperIntent = new Intent(context, ActivityStarterActivity.class); 48 wrapperIntent.putExtra(EXTRA_INTENT, intent); 49 wrapperIntent.putExtra(EXTRA_OPTIONS, options); 50 return wrapperIntent; 51 } 52 53 @Override onCreate(@ullable Bundle savedInstanceState)54 protected void onCreate(@Nullable Bundle savedInstanceState) { 55 super.onCreate(savedInstanceState); 56 57 if (savedInstanceState != null) { 58 // We're already waiting for the activity to finish, so don't start another instance. 59 mApplicationCrashed = true; 60 return; 61 } 62 63 Intent intent = getIntent(); 64 Intent startIntent = getExtraIntent(intent); 65 if (startIntent != null) { 66 try { 67 Bundle options = intent.getParcelableExtra(EXTRA_OPTIONS); 68 startActivityForResult(startIntent, REQUEST_CODE, options); 69 mApplicationCrashed = true; 70 } catch (ActivityNotFoundException e) { 71 Clog.w(TAG, "Failed to find activity for intent " + startIntent, e); 72 73 // TODO(b/123037263) I18n -- Move to resource 74 cancel("Failed to find application"); 75 } catch (SecurityException e) { 76 Clog.w(TAG, "No permission to launch intent " + startIntent, e); 77 78 // TODO(b/123037263) I18n -- Move to resource 79 cancel("No permission to launch application"); 80 } 81 } else { 82 throw new IllegalArgumentException( 83 "Couldn't find EXTRA_INTENT for activity starter activity"); 84 } 85 } 86 87 @Override onDestroy()88 protected void onDestroy() { 89 super.onDestroy(); 90 91 if (!isFinishing()) { 92 // The system is temporarily killing us, so ignore for now. 93 return; 94 } 95 96 if (mApplicationCrashed) { 97 Clog.w(TAG, "Activity crashed for intent " + getExtraIntent(getIntent())); 98 99 // TODO(b/123037263) I18n -- Move to resource 100 Toast.makeText(this, "Tried to start an external application but it crashed.", 101 Toast.LENGTH_SHORT).show(); 102 } 103 } 104 105 @Override onActivityResult(int requestCode, int resultCode, Intent data)106 public void onActivityResult(int requestCode, int resultCode, Intent data) { 107 if (requestCode == REQUEST_CODE) { 108 mApplicationCrashed = false; 109 setResult(resultCode, data); 110 finish(); 111 } else { 112 super.onActivityResult(requestCode, resultCode, data); 113 } 114 } 115 getExtraIntent(@ullable Intent intent)116 private @Nullable Intent getExtraIntent(@Nullable Intent intent) { 117 return intent == null ? null : intent.getParcelableExtra(EXTRA_INTENT); 118 } 119 cancel(@onNull CharSequence message)120 private void cancel(@NonNull CharSequence message) { 121 Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); 122 setResult(Activity.RESULT_CANCELED); 123 finish(); 124 } 125 } 126