Skip to content

Most visited

Recently visited

navigation
Notifications / Application / src / com.example.android.support.wearable.notifications /

MainActivity.java

1
/*
2
 * Copyright (C) 2014 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.example.android.support.wearable.notifications;
18
 
19
import android.app.Activity;
20
import android.app.Notification;
21
import android.content.Context;
22
import android.content.Intent;
23
import android.os.Bundle;
24
import android.os.Handler;
25
import android.os.Message;
26
import android.support.v4.app.NotificationManagerCompat;
27
import android.text.Editable;
28
import android.text.TextWatcher;
29
import android.view.View;
30
import android.view.ViewGroup;
31
import android.widget.AdapterView;
32
import android.widget.ArrayAdapter;
33
import android.widget.CheckBox;
34
import android.widget.CompoundButton;
35
import android.widget.EditText;
36
import android.widget.Spinner;
37
import android.widget.TextView;
38
 
39
import java.util.Arrays;
40
 
41
/**
42
 * Main activity which posts a notification when resumed, and allows customization
43
 * of that notification via controls.
44
 */
45
public class MainActivity extends Activity implements Handler.Callback {
46
    private static final int MSG_POST_NOTIFICATIONS = 0;
47
    private static final long POST_NOTIFICATIONS_DELAY_MS = 200;
48
 
49
    private Handler mHandler;
50
    private Spinner mPresetSpinner;
51
    private EditText mTitleEditText;
52
    private EditText mTextEditText;
53
    private TextWatcher mTextChangedListener;
54
    private Spinner mPrioritySpinner;
55
    private Spinner mActionsSpinner;
56
    private CheckBox mIncludeLargeIconCheckbox;
57
    private CheckBox mLocalOnlyCheckbox;
58
    private CheckBox mIncludeContentIntentCheckbox;
59
    private CheckBox mVibrateCheckbox;
60
    private BackgroundPickers mBackgroundPickers;
61
    private int postedNotificationCount = 0;
62
 
63
    @Override
64
    protected void onCreate(Bundle savedInstanceState) {
65
        super.onCreate(savedInstanceState);
66
        setContentView(R.layout.main);
67
 
68
        mHandler = new Handler(this);
69
        mTextChangedListener = new UpdateNotificationsOnTextChangeListener();
70
 
71
        initPresetSpinner();
72
        initTitleEditText();
73
        initTextEditText();
74
        initPrioritySpinner();
75
        initActionsSpinner();
76
        initIncludeLargeIconCheckbox();
77
        initLocalOnlyCheckbox();
78
        initIncludeContentIntentCheckbox();
79
        initVibrateCheckbox();
80
        initBackgroundPickers();
81
 
82
        NotificationPreset preset = NotificationPresets.PRESETS[
83
                mPresetSpinner.getSelectedItemPosition()];
84
        updateTextEditors(preset);
85
    }
86
 
87
    @Override
88
    protected void onResume() {
89
        super.onResume();
90
        updateNotifications(false /* cancelExisting */);
91
    }
92
 
93
    private void initPresetSpinner() {
94
        mPresetSpinner = (Spinner) findViewById(R.id.preset_spinner);
95
        mPresetSpinner.setAdapter(new NamedPresetSpinnerArrayAdapter(this,
96
                NotificationPresets.PRESETS));
97
        mPresetSpinner.post(new Runnable() {
98
            @Override
99
            public void run() {
100
                mPresetSpinner.setOnItemSelectedListener(new PresetSpinnerListener());
101
            }
102
        });
103
    }
104
 
105
    private void initTitleEditText() {
106
        mTitleEditText = (EditText) findViewById(R.id.title_editor);
107
    }
108
 
109
    private void initTextEditText() {
110
        mTextEditText = (EditText) findViewById(R.id.text_editor);
111
    }
112
 
113
    private void initPrioritySpinner() {
114
        mPrioritySpinner = (Spinner) findViewById(R.id.priority_spinner);
115
        mPrioritySpinner.setAdapter(new NamedPresetSpinnerArrayAdapter(this,
116
                PriorityPresets.PRESETS));
117
        mPrioritySpinner.setSelection(Arrays.asList(PriorityPresets.PRESETS)
118
                .indexOf(PriorityPresets.DEFAULT));
119
        mPrioritySpinner.post(new Runnable() {
120
            @Override
121
            public void run() {
122
                mPrioritySpinner.setOnItemSelectedListener(
123
                        new UpdateNotificationsOnItemSelectedListener(true /* cancelExisting */));
124
            }
125
        });
126
    }
127
 
128
    private void initActionsSpinner() {
129
        mActionsSpinner = (Spinner) findViewById(R.id.actions_spinner);
130
        mActionsSpinner.setAdapter(new NamedPresetSpinnerArrayAdapter(this,
131
                ActionsPresets.PRESETS));
132
        mActionsSpinner.post(new Runnable() {
133
            @Override
134
            public void run() {
135
                mActionsSpinner.setOnItemSelectedListener(
136
                        new UpdateNotificationsOnItemSelectedListener(false /* cancelExisting */));
137
            }
138
        });
139
    }
140
 
141
    private void initIncludeLargeIconCheckbox() {
142
        mIncludeLargeIconCheckbox = (CheckBox) findViewById(R.id.include_large_icon_checkbox);
143
        mIncludeLargeIconCheckbox.setOnCheckedChangeListener(
144
                new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */));
145
    }
146
 
147
    private void initLocalOnlyCheckbox() {
148
        mLocalOnlyCheckbox = (CheckBox) findViewById(R.id.local_only_checkbox);
149
        mLocalOnlyCheckbox.setOnCheckedChangeListener(
150
                new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */));
151
    }
152
 
153
    private void initIncludeContentIntentCheckbox() {
154
        mIncludeContentIntentCheckbox = (CheckBox) findViewById(
155
                R.id.include_content_intent_checkbox);
156
        mIncludeContentIntentCheckbox.setOnCheckedChangeListener(
157
                new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */));
158
    }
159
 
160
    private void initVibrateCheckbox() {
161
        mVibrateCheckbox = (CheckBox) findViewById(R.id.vibrate_checkbox);
162
        mVibrateCheckbox.setOnCheckedChangeListener(
163
                new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */));
164
    }
165
 
166
    private void initBackgroundPickers() {
167
        mBackgroundPickers = new BackgroundPickers(
168
                (ViewGroup) findViewById(R.id.background_pickers),
169
                new BackgroundPickerListener());
170
    }
171
 
172
    private void updateTextEditors(NotificationPreset preset) {
173
        mTitleEditText.setText(getString(preset.titleResId));
174
        mTextEditText.setText(getString(preset.textResId));
175
        if (preset == NotificationPresets.BASIC) {
176
            findViewById(R.id.title_edit_field).setVisibility(View.VISIBLE);
177
            mTitleEditText.addTextChangedListener(mTextChangedListener);
178
            findViewById(R.id.text_edit_field).setVisibility(View.VISIBLE);
179
            mTextEditText.addTextChangedListener(mTextChangedListener);
180
        } else {
181
            findViewById(R.id.title_edit_field).setVisibility(View.GONE);
182
            mTitleEditText.removeTextChangedListener(mTextChangedListener);
183
            findViewById(R.id.text_edit_field).setVisibility(View.GONE);
184
            mTextEditText.removeTextChangedListener(mTextChangedListener);
185
        }
186
    }
187
 
188
    /**
189
     * Begin to re-post the sample notification(s).
190
     */
191
    private void updateNotifications(boolean cancelExisting) {
192
        // Disable messages to skip notification deleted messages during cancel.
193
        sendBroadcast(new Intent(NotificationIntentReceiver.ACTION_DISABLE_MESSAGES)
194
                .setClass(this, NotificationIntentReceiver.class));
195
 
196
        if (cancelExisting) {
197
            // Cancel all existing notifications to trigger fresh-posting behavior: For example,
198
            // switching from HIGH to LOW priority does not cause a reordering in Notification Shade.
199
            NotificationManagerCompat.from(this).cancelAll();
200
            postedNotificationCount = 0;
201
 
202
            // Post the updated notifications on a delay to avoid a cancel+post race condition
203
            // with notification manager.
204
            mHandler.removeMessages(MSG_POST_NOTIFICATIONS);
205
            mHandler.sendEmptyMessageDelayed(MSG_POST_NOTIFICATIONS, POST_NOTIFICATIONS_DELAY_MS);
206
        } else {
207
            postNotifications();
208
        }
209
    }
210
 
211
    /**
212
     * Post the sample notification(s) using current options.
213
     */
214
    private void postNotifications() {
215
        sendBroadcast(new Intent(NotificationIntentReceiver.ACTION_ENABLE_MESSAGES)
216
                .setClass(this, NotificationIntentReceiver.class));
217
 
218
        NotificationPreset preset = NotificationPresets.PRESETS[
219
                mPresetSpinner.getSelectedItemPosition()];
220
        CharSequence titlePreset = mTitleEditText.getText();
221
        CharSequence textPreset = mTextEditText.getText();
222
        PriorityPreset priorityPreset = PriorityPresets.PRESETS[
223
                mPrioritySpinner.getSelectedItemPosition()];
224
        ActionsPreset actionsPreset = ActionsPresets.PRESETS[
225
                mActionsSpinner.getSelectedItemPosition()];
226
        if (preset.actionsRequired() && actionsPreset == ActionsPresets.NO_ACTIONS_PRESET) {
227
            // If actions are required, but the no-actions preset was selected, change presets.
228
            actionsPreset = ActionsPresets.SINGLE_ACTION_PRESET;
229
            mActionsSpinner.setSelection(Arrays.asList(ActionsPresets.PRESETS).indexOf(
230
                    actionsPreset), true);
231
        }
232
        NotificationPreset.BuildOptions options = new NotificationPreset.BuildOptions(
233
                titlePreset,
234
                textPreset,
235
                priorityPreset,
236
                actionsPreset,
237
                mIncludeLargeIconCheckbox.isChecked(),
238
                mLocalOnlyCheckbox.isChecked(),
239
                mIncludeContentIntentCheckbox.isChecked(),
240
                mVibrateCheckbox.isChecked(),
241
                mBackgroundPickers.getRes());
242
        Notification[] notifications = preset.buildNotifications(this, options);
243
 
244
        // Post new notifications
245
        for (int i = 0; i < notifications.length; i++) {
246
            NotificationManagerCompat.from(this).notify(i, notifications[i]);
247
        }
248
        // Cancel any that are beyond the current count.
249
        for (int i = notifications.length; i < postedNotificationCount; i++) {
250
            NotificationManagerCompat.from(this).cancel(i);
251
        }
252
        postedNotificationCount = notifications.length;
253
    }
254
 
255
    @Override
256
    public boolean handleMessage(Message message) {
257
        switch (message.what) {
258
            case MSG_POST_NOTIFICATIONS:
259
                postNotifications();
260
                return true;
261
        }
262
        return false;
263
    }
264
 
265
    private class PresetSpinnerListener implements AdapterView.OnItemSelectedListener {
266
        @Override
267
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
268
            NotificationPreset preset = NotificationPresets.PRESETS[position];
269
            mBackgroundPickers.generatePickers(preset.countBackgroundPickersRequired());
270
            updateTextEditors(preset);
271
            updateNotifications(false /* cancelExisting */);
272
        }
273
 
274
        @Override
275
        public void onNothingSelected(AdapterView<?> adapterView) {
276
        }
277
    }
278
 
279
    private class UpdateNotificationsOnTextChangeListener implements TextWatcher {
280
        @Override
281
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
282
        }
283
 
284
        public void onTextChanged(CharSequence s, int start, int before, int count) {
285
        }
286
 
287
        @Override
288
        public void afterTextChanged(Editable s) {
289
            updateNotifications(false /* cancelExisting */);
290
        }
291
    }
292
 
293
    private class UpdateNotificationsOnItemSelectedListener
294
            implements AdapterView.OnItemSelectedListener {
295
        private final boolean mCancelExisting;
296
 
297
        public UpdateNotificationsOnItemSelectedListener(boolean cancelExisting) {
298