1 package com.android.car.media; 2 3 import android.app.PendingIntent; 4 import android.os.Bundle; 5 import android.util.Log; 6 import android.view.LayoutInflater; 7 import android.view.View; 8 import android.view.ViewGroup; 9 import android.widget.Button; 10 11 import androidx.annotation.NonNull; 12 import androidx.fragment.app.Fragment; 13 14 import com.android.car.apps.common.UxrTextView; 15 16 /** 17 * A {@link Fragment} that displays the playback state error. 18 */ 19 public class ErrorFragment extends Fragment { 20 private final String TAG = "ErrorFragment"; 21 22 private static final String ERROR_RESOLUTION_ACTION_MESSAGE = "ERROR_RESOLUTION_ACTION_MESSAGE"; 23 private static final String ERROR_RESOLUTION_ACTION_LABEL = "ERROR_RESOLUTION_ACTION_LABEL"; 24 private static final String ERROR_RESOLUTION_ACTION_INTENT = "ERROR_RESOLUTION_ACTION_INTENT"; 25 26 // mErrorMessageView is defined explicitly as a UxrTextView instead of a TextView to 27 // provide clarity as it may be misleading to assume that mErrorMessageView extends all TextView 28 // methods. In addition, it increases discoverability of runtime issues that may occur. 29 private UxrTextView mErrorMessageView; 30 private Button mErrorButton; 31 32 private String mErrorMessageStr; 33 private String mErrorLabel; 34 private PendingIntent mPendingIntent; 35 newInstance(String message, String label, PendingIntent intent)36 public static ErrorFragment newInstance(String message, String label, PendingIntent intent) { 37 ErrorFragment fragment = new ErrorFragment(); 38 39 Bundle args = new Bundle(); 40 args.putString(ERROR_RESOLUTION_ACTION_MESSAGE, message); 41 args.putString(ERROR_RESOLUTION_ACTION_LABEL, label); 42 args.putParcelable(ERROR_RESOLUTION_ACTION_INTENT, intent); 43 fragment.setArguments(args); 44 45 return fragment; 46 } 47 48 @Override onCreateView(@onNull LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState)49 public View onCreateView(@NonNull LayoutInflater inflater, final ViewGroup container, 50 Bundle savedInstanceState) { 51 View view = inflater.inflate(R.layout.fragment_error, container, false); 52 53 mErrorMessageView = view.findViewById(R.id.error_message); 54 mErrorButton = view.findViewById(R.id.error_button); 55 56 Bundle args = getArguments(); 57 if (args != null) { 58 mErrorMessageStr = args.getString(ERROR_RESOLUTION_ACTION_MESSAGE); 59 mErrorLabel = args.getString(ERROR_RESOLUTION_ACTION_LABEL); 60 mPendingIntent = args.getParcelable(ERROR_RESOLUTION_ACTION_INTENT); 61 } 62 63 if (mErrorMessageStr == null) { 64 Log.e(TAG, "ErrorFragment does not have an error message"); 65 return view; 66 } 67 68 mErrorMessageView.setText(mErrorMessageStr); 69 70 // Only an error message is required. Fragments without a provided message and label 71 // have these elements omitted. 72 if (mErrorLabel != null && mPendingIntent != null) { 73 mErrorButton.setText(mErrorLabel); 74 mErrorButton.setOnClickListener(v -> { 75 try { 76 mPendingIntent.send(); 77 } catch (PendingIntent.CanceledException e) { 78 if (Log.isLoggable(TAG, Log.ERROR)) { 79 Log.e(TAG, "Pending intent canceled"); 80 } 81 } 82 }); 83 mErrorButton.setVisibility(View.VISIBLE); 84 } else { 85 mErrorButton.setVisibility(View.GONE); 86 } 87 88 return view; 89 } 90 } 91