SampleSliceProvider.java revision 8a71dde4314b29493bca91790ce5aec4ea789c47
1/*
2 * Copyright 2017 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
17package com.example.androidx.slice.demos;
18
19import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
20
21import android.app.PendingIntent;
22import android.content.ContentResolver;
23import android.content.Context;
24import android.content.Intent;
25import android.graphics.drawable.Icon;
26import android.net.Uri;
27import android.net.wifi.WifiManager;
28import android.provider.Settings;
29import android.support.annotation.NonNull;
30import android.text.SpannableString;
31import android.text.format.DateUtils;
32import android.text.style.ForegroundColorSpan;
33
34import androidx.app.slice.Slice;
35import androidx.app.slice.SliceProvider;
36import androidx.app.slice.builders.GridBuilder;
37import androidx.app.slice.builders.ListBuilder;
38import androidx.app.slice.builders.MessagingSliceBuilder;
39
40/**
41 * Examples of using slice template builders.
42 */
43public class SampleSliceProvider extends SliceProvider {
44
45    public static final String ACTION_WIFI_CHANGED =
46            "com.example.androidx.slice.action.WIFI_CHANGED";
47    public static final String ACTION_TOAST =
48            "com.example.androidx.slice.action.TOAST";
49    public static final String EXTRA_TOAST_MESSAGE = "com.example.androidx.extra.TOAST_MESSAGE";
50
51    public static final String[] URI_PATHS = {"message", "wifi", "note", "ride", "toggle",
52            "toggle2", "contact", "gallery", "weather", "reservation"};
53
54    /**
55     * @return Uri with the provided path
56     */
57    public static Uri getUri(String path, Context context) {
58        return new Uri.Builder()
59                .scheme(ContentResolver.SCHEME_CONTENT)
60                .authority(context.getPackageName())
61                .appendPath(path)
62                .build();
63    }
64
65    @Override
66    public boolean onCreateSliceProvider() {
67        return true;
68    }
69
70    @NonNull
71    @Override
72    public Uri onMapIntentToUri(Intent intent) {
73        return getUri("wifi", getContext());
74    }
75
76    @Override
77    public Slice onBindSlice(Uri sliceUri) {
78        String path = sliceUri.getPath();
79        switch (path) {
80            case "/message":
81                return createMessagingSlice(sliceUri);
82            case "/wifi":
83                return createWifiSlice(sliceUri);
84            case "/note":
85                return createNoteSlice(sliceUri);
86            case "/ride":
87                return createRideSlice(sliceUri);
88            case "/toggle":
89                return createCustomToggleSlice(sliceUri);
90            case "/toggle2":
91                return createTwoCustomToggleSlices(sliceUri);
92            case "/contact":
93                return createContact(sliceUri);
94            case "/gallery":
95                return createGallery(sliceUri);
96            case "/weather":
97                return createWeather(sliceUri);
98            case "/reservation":
99                return createReservationSlice(sliceUri);
100        }
101        throw new IllegalArgumentException("Unknown uri " + sliceUri);
102    }
103
104    private Slice createWeather(Uri sliceUri) {
105        return new GridBuilder(getContext(), sliceUri)
106                .addCell(cb -> cb
107                        .addLargeImage(Icon.createWithResource(getContext(), R.drawable.weather_1))
108                        .addText("MON")
109                        .addTitleText("69\u00B0"))
110                .addCell(cb -> cb
111                        .addLargeImage(Icon.createWithResource(getContext(), R.drawable.weather_2))
112                        .addText("TUE")
113                        .addTitleText("71\u00B0"))
114                .addCell(cb -> cb
115                        .addLargeImage(Icon.createWithResource(getContext(), R.drawable.weather_3))
116                        .addText("WED")
117                        .addTitleText("76\u00B0"))
118                .addCell(cb -> cb
119                        .addLargeImage(Icon.createWithResource(getContext(), R.drawable.weather_4))
120                        .addText("THU")
121                        .addTitleText("72\u00B0"))
122                .addCell(cb -> cb
123                        .addLargeImage(Icon.createWithResource(getContext(), R.drawable.weather_1))
124                        .addText("FRI")
125                        .addTitleText("68\u00B0"))
126                .build();
127    }
128
129    private Slice createGallery(Uri sliceUri) {
130        return new ListBuilder(getContext(), sliceUri)
131                .setColor(0xff4285F4)
132                .addRow(b -> b
133                    .setTitle("Family trip to Hawaii")
134                    .setSubtitle("Sep 30, 2017 - Oct 2, 2017")
135                    .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_cast),
136                            getBroadcastIntent(ACTION_TOAST, "cast photo album"))
137                    .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_share),
138                            getBroadcastIntent(ACTION_TOAST, "share photo album")))
139                .addGrid(b -> b
140                    .addCell(cb -> cb
141                        .addLargeImage(Icon.createWithResource(getContext(), R.drawable.slices_1)))
142                    .addCell(cb -> cb
143                        .addLargeImage(Icon.createWithResource(getContext(), R.drawable.slices_2)))
144                    .addCell(cb -> cb
145                        .addLargeImage(Icon.createWithResource(getContext(), R.drawable.slices_3)))
146                    .addCell(cb -> cb
147                        .addLargeImage(Icon.createWithResource(getContext(), R.drawable.slices_4))))
148                .build();
149    }
150
151    private Slice createContact(Uri sliceUri) {
152        return new ListBuilder(getContext(), sliceUri)
153                .setColor(0xff3949ab)
154                .addRow(b -> b
155                        .setTitle("Mady Pitza")
156                        .setSubtitle("Frequently contacted contact")
157                        .addEndItem(Icon.createWithResource(getContext(), R.drawable.mady)))
158                .addGrid(b -> b
159                        .addCell(cb -> cb
160                            .addImage(Icon.createWithResource(getContext(), R.drawable.ic_call))
161                            .addText("Call")
162                            .setContentIntent(getBroadcastIntent(ACTION_TOAST, "call")))
163                        .addCell(cb -> cb
164                            .addImage(Icon.createWithResource(getContext(), R.drawable.ic_text))
165                            .addText("Text")
166                            .setContentIntent(getBroadcastIntent(ACTION_TOAST, "text")))
167                        .addCell(cb ->cb
168                            .addImage(Icon.createWithResource(getContext(), R.drawable.ic_video))
169                            .setContentIntent(getBroadcastIntent(ACTION_TOAST, "video"))
170                            .addText("Video"))
171                        .addCell(cb -> cb
172                            .addImage(Icon.createWithResource(getContext(), R.drawable.ic_email))
173                            .addText("Email")
174                            .setContentIntent(getBroadcastIntent(ACTION_TOAST, "email"))))
175                .build();
176    }
177
178    private Slice createMessagingSlice(Uri sliceUri) {
179        // TODO: Remote input.
180        return new MessagingSliceBuilder(getContext(), sliceUri)
181                .add(b -> b
182                        .addText("yo home \uD83C\uDF55, I emailed you the info")
183                        .addTimestamp(System.currentTimeMillis() - 20 * DateUtils.MINUTE_IN_MILLIS)
184                        .addSource(Icon.createWithResource(getContext(), R.drawable.mady)))
185                .add(b -> b
186                        .addText("just bought my tickets")
187                        .addTimestamp(System.currentTimeMillis() - 10 * DateUtils.MINUTE_IN_MILLIS))
188                .add(b -> b
189                        .addText("yay! can't wait for getContext() weekend!\n"
190                                + "\uD83D\uDE00")
191                        .addTimestamp(System.currentTimeMillis() - 5 * DateUtils.MINUTE_IN_MILLIS)
192                        .addSource(Icon.createWithResource(getContext(), R.drawable.mady)))
193                .build();
194
195    }
196
197    private Slice createNoteSlice(Uri sliceUri) {
198        // TODO: Remote input.
199        return new ListBuilder(getContext(), sliceUri)
200                .setColor(0xfff4b400)
201                .addRow(b -> b
202                    .setTitle("Create new note")
203                    .setSubtitle("with this note taking app")
204                    .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_create),
205                            getBroadcastIntent(ACTION_TOAST, "create note"))
206                    .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_voice),
207                            getBroadcastIntent(ACTION_TOAST, "voice note"))
208                    .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_camera),
209                            getIntent("android.media.action.IMAGE_CAPTURE")))
210                .build();
211    }
212
213    private Slice createReservationSlice(Uri sliceUri) {
214        return new ListBuilder(getContext(), sliceUri)
215                .setColor(0xffFF5252)
216                .addRow(b -> b
217                    .setTitle("Upcoming trip to Seattle")
218                    .setSubtitle("Feb 1 - 19 | 2 guests")
219                    .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_location),
220                            getBroadcastIntent(ACTION_TOAST, "show reservation location on map"))
221                    .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_text),
222                            getBroadcastIntent(ACTION_TOAST, "contact host")))
223                .addGrid(b -> b
224                    .addCell(cb -> cb
225                        .addLargeImage(
226                                Icon.createWithResource(getContext(), R.drawable.reservation))))
227                .addGrid(b -> b
228                    .addCell(cb -> cb
229                        .addTitleText("Check In")
230                        .addText("12:00 PM, Feb 1"))
231                    .addCell(cb -> cb
232                        .addTitleText("Check Out")
233                        .addText("11:00 AM, Feb 19")))
234                .build();
235    }
236
237    private Slice createRideSlice(Uri sliceUri) {
238        final ForegroundColorSpan colorSpan = new ForegroundColorSpan(0xff0F9D58);
239        SpannableString headerSubtitle = new SpannableString("Ride in 4 min");
240        headerSubtitle.setSpan(colorSpan, 8, headerSubtitle.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
241        SpannableString homeSubtitle = new SpannableString("12 miles | 12 min | $9.00");
242        homeSubtitle.setSpan(colorSpan, 20, homeSubtitle.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
243        SpannableString workSubtitle = new SpannableString("44 miles | 1 hour 45 min | $31.41");
244        workSubtitle.setSpan(colorSpan, 27, workSubtitle.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
245
246        return new ListBuilder(getContext(), sliceUri)
247                .setColor(0xff0F9D58)
248                .addRow(b -> b
249                    .setTitle("Work")
250                    .setSubtitle(workSubtitle)
251                    .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_work),
252                            getBroadcastIntent(ACTION_TOAST, "work")))
253                .addRow(b -> b
254                    .setTitle("Home")
255                    .setSubtitle("2 hours 33 min via 101")
256                    .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_home),
257                            getBroadcastIntent(ACTION_TOAST, "home")))
258                .build();
259    }
260
261    private Slice createCustomToggleSlice(Uri sliceUri) {
262        return new ListBuilder(getContext(), sliceUri)
263                .setColor(0xffff4081)
264                .addRow(b -> b
265                    .setTitle("Custom toggle")
266                    .setSubtitle("It can support two states")
267                    .addToggle(getBroadcastIntent(ACTION_TOAST, "star toggled"),
268                            true /* isChecked */,
269                            Icon.createWithResource(getContext(), R.drawable.toggle_star)))
270                .build();
271    }
272
273    private Slice createTwoCustomToggleSlices(Uri sliceUri) {
274        return new ListBuilder(getContext(), sliceUri)
275                .setColor(0xffff4081)
276                .addRow(b -> b
277                        .setTitle("2 toggles")
278                        .setSubtitle("each supports two states")
279                        .addToggle(getBroadcastIntent(ACTION_TOAST, "first star toggled"),
280                                true /* isChecked */,
281                                Icon.createWithResource(getContext(), R.drawable.toggle_star))
282                        .addToggle(getBroadcastIntent(ACTION_TOAST, "second star toggled"),
283                                false /* isChecked */,
284                                Icon.createWithResource(getContext(), R.drawable.toggle_star)))
285                .build();
286    }
287
288    private Slice createWifiSlice(Uri sliceUri) {
289        // Get wifi state
290        WifiManager wifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
291        int wifiState = wifiManager.getWifiState();
292        boolean wifiEnabled = false;
293        String state;
294        switch (wifiState) {
295            case WifiManager.WIFI_STATE_DISABLED:
296            case WifiManager.WIFI_STATE_DISABLING:
297                state = "disconnected";
298                break;
299            case WifiManager.WIFI_STATE_ENABLED:
300            case WifiManager.WIFI_STATE_ENABLING:
301                state = wifiManager.getConnectionInfo().getSSID();
302                wifiEnabled = true;
303                break;
304            case WifiManager.WIFI_STATE_UNKNOWN:
305            default:
306                state = ""; // just don't show anything?
307                break;
308        }
309        boolean finalWifiEnabled = wifiEnabled;
310        return new ListBuilder(getContext(), sliceUri)
311                .setColor(0xff4285f4)
312                .addRow(b -> b
313                    .setTitle("Wi-fi")
314                    .setTitleItem(Icon.createWithResource(getContext(), R.drawable.ic_wifi))
315                    .setSubtitle(state)
316                    .addToggle(getBroadcastIntent(ACTION_WIFI_CHANGED, null), finalWifiEnabled)
317                    .setContentIntent(getIntent(Settings.ACTION_WIFI_SETTINGS)))
318            .build();
319    }
320
321    private PendingIntent getIntent(String action) {
322        Intent intent = new Intent(action);
323        PendingIntent pi = PendingIntent.getActivity(getContext(), 0, intent, 0);
324        return pi;
325    }
326
327    private PendingIntent getBroadcastIntent(String action, String message) {
328        Intent intent = new Intent(action);
329        intent.setClass(getContext(), SliceBroadcastReceiver.class);
330        // Ensure a new PendingIntent is created for each message.
331        int requestCode = 0;
332        if (message != null) {
333            intent.putExtra(EXTRA_TOAST_MESSAGE, message);
334            requestCode = message.hashCode();
335        }
336        return PendingIntent.getBroadcast(getContext(), requestCode, intent,
337                PendingIntent.FLAG_UPDATE_CURRENT);
338    }
339}
340