package com.thebluealliance.androidclient.activities; import com.thebluealliance.androidclient.R; import com.thebluealliance.androidclient.types.ModelType; import android.annotation.TargetApi; import android.content.Intent; import android.nfc.NdefMessage; import android.nfc.NdefRecord; import android.nfc.NfcAdapter; import android.nfc.NfcEvent; import android.os.Build; import android.os.Bundle; import android.support.annotation.IntDef; import android.support.v7.app.AlertDialog; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.TextView; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.HashSet; import java.util.Set; /** * Provides the features that should be in every activity in the app: a navigation drawer, a search * button, and the ability to show and hide warning messages. Also provides Android Beam * functionality. */ public abstract class BaseActivity extends NavigationDrawerActivity implements NfcAdapter.CreateNdefMessageCallback { @IntDef({WARNING_OFFLINE, WARNING_FIRST_API_DOWN, WARNING_EVENT_DOWN}) @Retention(RetentionPolicy.SOURCE) public @interface WarningMessageType {} public static final int WARNING_OFFLINE = 3; public static final int WARNING_FIRST_API_DOWN = 2; public static final int WARNING_EVENT_DOWN = 1; public Set<Integer> activeMessages = new HashSet<>(); String beamUri; String shareUri; boolean searchEnabled = true; boolean shareEnabled = false; String modelKey = ""; ModelType modelType; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); NfcAdapter mNfcAdapter = NfcAdapter.getDefaultAdapter(this); if (mNfcAdapter != null) { // Register callback mNfcAdapter.setNdefPushMessageCallback(this, this); } } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); // Hide the shadow below the Action Bar if (getSupportActionBar() != null) { getSupportActionBar().setElevation(0); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.base_menu, menu); if (!searchEnabled) { menu.findItem(R.id.search).setVisible(false); } if (!shareEnabled) { menu.findItem(R.id.share).setVisible(false); } return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.search: startActivity(new Intent(this, SearchResultsActivity.class)); return true; case R.id.share: if (shareUri == null) return true; Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND); sharingIntent.setType("text/plain"); sharingIntent.putExtra(Intent.EXTRA_TEXT, shareUri); startActivity(Intent.createChooser(sharingIntent, getString(R.string.share_prompt))); return true; } return super.onOptionsItemSelected(item); } /** * By default, all activities that extend BaseActivity will show global warning messages. If * you don't want a subclass to show warning messages, override this and return false; * * @return true if this activity should show warning messages, false if otherwise */ public boolean shouldShowWarningMessages() { return true; } public void showWarningMessage(@WarningMessageType int messageType) { if (!shouldShowWarningMessages()) { return; } activeMessages.add(messageType); // The latest message to be shown might not be the highest priority // Find the highest priority active message and show that one displayMessageForMessageType(getHighestPriorityMessage()); } private void displayMessageForMessageType(@WarningMessageType int type) { View container = findViewById(R.id.root_snackbar_container); TextView message = (TextView) findViewById(R.id.root_snackbar_message); TextView action = (TextView) findViewById(R.id.root_snackbar_action); // Set default visibilities container.setVisibility(View.VISIBLE); message.setVisibility(View.VISIBLE); action.setVisibility(View.GONE); switch (type) { case WARNING_OFFLINE: message.setText(R.string.warning_offline_message); action.setVisibility(View.VISIBLE); action.setText(R.string.warning_more); action.setOnClickListener(v -> { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.warning_more_info); builder.setMessage(R.string.warning_offline_explanation); builder.setCancelable(true); builder.setNeutralButton(getString(R.string.warning_close), (dialog, which) -> dialog.cancel() ); builder.create().show(); }); break; case WARNING_EVENT_DOWN: message.setText(R.string.warning_event_down_message); action.setVisibility(View.VISIBLE); action.setText(R.string.warning_more); action.setOnClickListener(v -> { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.warning_more_info); builder.setMessage(R.string.warning_event_down_explanation); builder.setCancelable(true); builder.setNeutralButton(getString(R.string.warning_close), (dialog, which) -> dialog.cancel() ); builder.create().show(); }); break; case WARNING_FIRST_API_DOWN: message.setText(R.string.warning_first_down_message); action.setVisibility(View.VISIBLE); action.setText(R.string.warning_more); action.setOnClickListener(v -> { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.warning_more_info); builder.setMessage(R.string.warning_first_down_explanation); builder.setCancelable(true); builder.setNeutralButton(getString(R.string.warning_close), (dialog, which) -> dialog.cancel() ); builder.create().show(); }); break; } } public void dismissWarningMessage(@WarningMessageType int messageType) { activeMessages.remove(messageType); if (activeMessages.isEmpty()) { // There are no more active messages; hide the container findViewById(R.id.root_snackbar_container).setVisibility(View.GONE); } else { // There are more active messages; find the highest priority one and display it displayMessageForMessageType(getHighestPriorityMessage()); } } public void dismissAllWarningMessages() { activeMessages.clear(); findViewById(R.id.root_snackbar_container).setVisibility(View.GONE); } private @WarningMessageType int getHighestPriorityMessage() { @WarningMessageType int highestPriority = Integer.MIN_VALUE; for (int type : activeMessages) { if (type > highestPriority) { highestPriority = type; } } return highestPriority; } public void setShareUri(String uri) { shareUri = uri; } public void setShareEnabled(boolean enabled) { shareEnabled = enabled; } public void setBeamUri(String uri) { beamUri = uri; } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public NdefMessage createNdefMessage(NfcEvent nfcEvent) { if (beamUri == null || beamUri.isEmpty()) { return null; } else { return new NdefMessage(new NdefRecord[]{NdefRecord.createMime("application/vnd.com.thebluealliance.androidclient", beamUri.getBytes())}); } } protected void setSearchEnabled(boolean enabled) { searchEnabled = enabled; invalidateOptionsMenu(); } protected void setModelKey(String key, ModelType type) { modelKey = key; modelType = type; } }