/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.support.wearable.notifications; import android.app.Activity; import android.app.Notification; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v4.app.NotificationManagerCompat; import android.text.Editable; import android.text.TextWatcher; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; import java.util.Arrays; /** * Main activity which posts a notification when resumed, and allows customization * of that notification via controls. */ public class MainActivity extends Activity implements Handler.Callback { private static final int MSG_POST_NOTIFICATIONS = 0; private static final long POST_NOTIFICATIONS_DELAY_MS = 200; private Handler mHandler; private Spinner mPresetSpinner; private EditText mTitleEditText; private EditText mTextEditText; private TextWatcher mTextChangedListener; private Spinner mPrioritySpinner; private Spinner mActionsSpinner; private CheckBox mIncludeLargeIconCheckbox; private CheckBox mLocalOnlyCheckbox; private CheckBox mIncludeContentIntentCheckbox; private CheckBox mVibrateCheckbox; private BackgroundPickers mBackgroundPickers; private int postedNotificationCount = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mHandler = new Handler(this); mTextChangedListener = new UpdateNotificationsOnTextChangeListener(); initPresetSpinner(); initTitleEditText(); initTextEditText(); initPrioritySpinner(); initActionsSpinner(); initIncludeLargeIconCheckbox(); initLocalOnlyCheckbox(); initIncludeContentIntentCheckbox(); initVibrateCheckbox(); initBackgroundPickers(); NotificationPreset preset = NotificationPresets.PRESETS[ mPresetSpinner.getSelectedItemPosition()]; updateTextEditors(preset); } @Override protected void onResume() { super.onResume(); updateNotifications(false /* cancelExisting */); } private void initPresetSpinner() { mPresetSpinner = (Spinner) findViewById(R.id.preset_spinner); mPresetSpinner.setAdapter(new NamedPresetSpinnerArrayAdapter(this, NotificationPresets.PRESETS)); mPresetSpinner.post(new Runnable() { @Override public void run() { mPresetSpinner.setOnItemSelectedListener(new PresetSpinnerListener()); } }); } private void initTitleEditText() { mTitleEditText = (EditText) findViewById(R.id.title_editor); } private void initTextEditText() { mTextEditText = (EditText) findViewById(R.id.text_editor); } private void initPrioritySpinner() { mPrioritySpinner = (Spinner) findViewById(R.id.priority_spinner); mPrioritySpinner.setAdapter(new NamedPresetSpinnerArrayAdapter(this, PriorityPresets.PRESETS)); mPrioritySpinner.setSelection(Arrays.asList(PriorityPresets.PRESETS) .indexOf(PriorityPresets.DEFAULT)); mPrioritySpinner.post(new Runnable() { @Override public void run() { mPrioritySpinner.setOnItemSelectedListener( new UpdateNotificationsOnItemSelectedListener(true /* cancelExisting */)); } }); } private void initActionsSpinner() { mActionsSpinner = (Spinner) findViewById(R.id.actions_spinner); mActionsSpinner.setAdapter(new NamedPresetSpinnerArrayAdapter(this, ActionsPresets.PRESETS)); mActionsSpinner.post(new Runnable() { @Override public void run() { mActionsSpinner.setOnItemSelectedListener( new UpdateNotificationsOnItemSelectedListener(false /* cancelExisting */)); } }); } private void initIncludeLargeIconCheckbox() { mIncludeLargeIconCheckbox = (CheckBox) findViewById(R.id.include_large_icon_checkbox); mIncludeLargeIconCheckbox.setOnCheckedChangeListener( new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */)); } private void initLocalOnlyCheckbox() { mLocalOnlyCheckbox = (CheckBox) findViewById(R.id.local_only_checkbox); mLocalOnlyCheckbox.setOnCheckedChangeListener( new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */)); } private void initIncludeContentIntentCheckbox() { mIncludeContentIntentCheckbox = (CheckBox) findViewById( R.id.include_content_intent_checkbox); mIncludeContentIntentCheckbox.setOnCheckedChangeListener( new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */)); } private void initVibrateCheckbox() { mVibrateCheckbox = (CheckBox) findViewById(R.id.vibrate_checkbox); mVibrateCheckbox.setOnCheckedChangeListener( new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */)); } private void initBackgroundPickers() { mBackgroundPickers = new BackgroundPickers( (ViewGroup) findViewById(R.id.background_pickers), new BackgroundPickerListener()); } private void updateTextEditors(NotificationPreset preset) { mTitleEditText.setText(getString(preset.titleResId)); mTextEditText.setText(getString(preset.textResId)); if (preset == NotificationPresets.BASIC) { findViewById(R.id.title_edit_field).setVisibility(View.VISIBLE); mTitleEditText.addTextChangedListener(mTextChangedListener); findViewById(R.id.text_edit_field).setVisibility(View.VISIBLE); mTextEditText.addTextChangedListener(mTextChangedListener); } else { findViewById(R.id.title_edit_field).setVisibility(View.GONE); mTitleEditText.removeTextChangedListener(mTextChangedListener); findViewById(R.id.text_edit_field).setVisibility(View.GONE); mTextEditText.removeTextChangedListener(mTextChangedListener); } } /** * Begin to re-post the sample notification(s). */ private void updateNotifications(boolean cancelExisting) { // Disable messages to skip notification deleted messages during cancel. sendBroadcast(new Intent(NotificationIntentReceiver.ACTION_DISABLE_MESSAGES) .setClass(this, NotificationIntentReceiver.class)); if (cancelExisting) { // Cancel all existing notifications to trigger fresh-posting behavior: For example, // switching from HIGH to LOW priority does not cause a reordering in Notification Shade. NotificationManagerCompat.from(this).cancelAll(); postedNotificationCount = 0; // Post the updated notifications on a delay to avoid a cancel+post race condition // with notification manager. mHandler.removeMessages(MSG_POST_NOTIFICATIONS); mHandler.sendEmptyMessageDelayed(MSG_POST_NOTIFICATIONS, POST_NOTIFICATIONS_DELAY_MS); } else { postNotifications(); } } /** * Post the sample notification(s) using current options. */ private void postNotifications() { sendBroadcast(new Intent(NotificationIntentReceiver.ACTION_ENABLE_MESSAGES) .setClass(this, NotificationIntentReceiver.class)); NotificationPreset preset = NotificationPresets.PRESETS[ mPresetSpinner.getSelectedItemPosition()]; CharSequence titlePreset = mTitleEditText.getText(); CharSequence textPreset = mTextEditText.getText(); PriorityPreset priorityPreset = PriorityPresets.PRESETS[ mPrioritySpinner.getSelectedItemPosition()]; ActionsPreset actionsPreset = ActionsPresets.PRESETS[ mActionsSpinner.getSelectedItemPosition()]; if (preset.actionsRequired() && actionsPreset == ActionsPresets.NO_ACTIONS_PRESET) { // If actions are required, but the no-actions preset was selected, change presets. actionsPreset = ActionsPresets.SINGLE_ACTION_PRESET; mActionsSpinner.setSelection(Arrays.asList(ActionsPresets.PRESETS).indexOf( actionsPreset), true); } NotificationPreset.BuildOptions options = new NotificationPreset.BuildOptions( titlePreset, textPreset, priorityPreset, actionsPreset, mIncludeLargeIconCheckbox.isChecked(), mLocalOnlyCheckbox.isChecked(), mIncludeContentIntentCheckbox.isChecked(), mVibrateCheckbox.isChecked(), mBackgroundPickers.getRes()); Notification[] notifications = preset.buildNotifications(this, options); // Post new notifications for (int i = 0; i < notifications.length; i++) { NotificationManagerCompat.from(this).notify(i, notifications[i]); } // Cancel any that are beyond the current count. for (int i = notifications.length; i < postedNotificationCount; i++) { NotificationManagerCompat.from(this).cancel(i); } postedNotificationCount = notifications.length; } @Override public boolean handleMessage(Message message) { switch (message.what) { case MSG_POST_NOTIFICATIONS: postNotifications(); return true; } return false; } private class PresetSpinnerListener implements AdapterView.OnItemSelectedListener { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { NotificationPreset preset = NotificationPresets.PRESETS[position]; mBackgroundPickers.generatePickers(preset.countBackgroundPickersRequired()); updateTextEditors(preset); updateNotifications(false /* cancelExisting */); } @Override public void onNothingSelected(AdapterView adapterView) { } } private class UpdateNotificationsOnTextChangeListener implements TextWatcher { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { updateNotifications(false /* cancelExisting */); } } private class UpdateNotificationsOnItemSelectedListener implements AdapterView.OnItemSelectedListener { private final boolean mCancelExisting; public UpdateNotificationsOnItemSelectedListener(boolean cancelExisting) { mCancelExisting = cancelExisting; } @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { updateNotifications(mCancelExisting); } @Override public void onNothingSelected(AdapterView adapterView) { } } private class UpdateNotificationsOnCheckedChangeListener implements CompoundButton.OnCheckedChangeListener { private final boolean mCancelExisting; public UpdateNotificationsOnCheckedChangeListener(boolean cancelExisting) { mCancelExisting = cancelExisting; } @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { updateNotifications(mCancelExisting); } } private class BackgroundPickerListener implements BackgroundPickers.OnBackgroundPickersChangedListener { @Override public void onBackgroundPickersChanged(BackgroundPickers pickers) { updateNotifications(false /* cancelExisting */); } } private class NamedPresetSpinnerArrayAdapter extends ArrayAdapter { public NamedPresetSpinnerArrayAdapter(Context context, NamedPreset[] presets) { super(context, R.layout.simple_spinner_item, presets); } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { TextView view = (TextView) super.getDropDownView(position, convertView, parent); view.setText(getString(getItem(position).nameResId)); return view; } @Override public View getView(int position, View convertView, ViewGroup parent) { TextView view = (TextView) getLayoutInflater().inflate( android.R.layout.simple_spinner_item, parent, false); view.setText(getString(getItem(position).nameResId)); return view; } } }