-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathintents.html
More file actions
871 lines (824 loc) · 88.9 KB
/
intents.html
File metadata and controls
871 lines (824 loc) · 88.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Android Development: Lecture Notes</title>
<meta name="description" content="Lecture Notes for INFO 448: Android Development.">
<meta name="generator" content="bookdown 0.5 and GitBook 2.6.7">
<meta property="og:title" content="Android Development: Lecture Notes" />
<meta property="og:type" content="book" />
<meta property="og:url" content="https://info448.github.io/" />
<meta property="og:image" content="https://info448.github.io/img/android_icon_transparent.png" />
<meta property="og:description" content="Lecture Notes for INFO 448: Android Development." />
<meta name="github-repo" content="info448/book" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="Android Development: Lecture Notes" />
<meta name="twitter:description" content="Lecture Notes for INFO 448: Android Development." />
<meta name="twitter:image" content="https://info448.github.io/img/android_icon_transparent.png" />
<meta name="author" content="Joel Ross">
<meta name="date" content="2018-11-19">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="shortcut icon" href="img/android_icon_transparent.png" type="image/x-icon">
<link rel="prev" href="fragments.html">
<link rel="next" href="notifications-settings.html">
<script src="libs/jquery-2.2.3/jquery.min.js"></script>
<link href="libs/gitbook-2.6.7/css/style.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-bookdown.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-highlight.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-search.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-fontsettings.css" rel="stylesheet" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-98444716-1', 'auto');
ga('send', 'pageview');
</script>
<style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
</style>
<link rel="stylesheet" href="css/style.css" type="text/css" />
</head>
<body>
<div class="book without-animation with-summary font-size-2 font-family-1" data-basepath=".">
<div class="book-summary">
<nav role="navigation">
<ul class="summary">
<li><a href="./" class="title">Android Development</a></li>
<li class="divider"></li>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html"><i class="fa fa-check"></i>About this Book</a></li>
<li class="part"><span><b>I Lectures</b></span></li>
<li class="chapter" data-level="1" data-path="introduction.html"><a href="introduction.html"><i class="fa fa-check"></i><b>1</b> Introduction</a><ul>
<li class="chapter" data-level="1.1" data-path="introduction.html"><a href="introduction.html#android-history"><i class="fa fa-check"></i><b>1.1</b> Android History</a><ul>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#android-versions"><i class="fa fa-check"></i>Android Versions</a></li>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#legal-battles"><i class="fa fa-check"></i>Legal Battles</a></li>
</ul></li>
<li class="chapter" data-level="1.2" data-path="introduction.html"><a href="introduction.html#building-apps"><i class="fa fa-check"></i><b>1.2</b> Building Apps</a><ul>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#creating-a-project"><i class="fa fa-check"></i>Creating a Project</a></li>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#running-the-app"><i class="fa fa-check"></i>Running the App</a></li>
</ul></li>
<li class="chapter" data-level="1.3" data-path="introduction.html"><a href="introduction.html#app-source-code"><i class="fa fa-check"></i><b>1.3</b> App Source Code</a><ul>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#xml-resources"><i class="fa fa-check"></i>XML Resources</a></li>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#the-manifest"><i class="fa fa-check"></i>The Manifest</a></li>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#java-activities"><i class="fa fa-check"></i>Java Activities</a></li>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#gradle-scripts"><i class="fa fa-check"></i>Gradle Scripts</a></li>
</ul></li>
<li class="chapter" data-level="1.4" data-path="introduction.html"><a href="introduction.html#logging-adb"><i class="fa fa-check"></i><b>1.4</b> Logging & ADB</a><ul>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#log-methods"><i class="fa fa-check"></i>Log Methods</a></li>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#logcat"><i class="fa fa-check"></i>Logcat</a></li>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#toast"><i class="fa fa-check"></i>Toast</a></li>
</ul></li>
<li class="chapter" data-level="1.5" data-path="introduction.html"><a href="introduction.html#adding-interaction"><i class="fa fa-check"></i><b>1.5</b> Adding Interaction</a></li>
<li class="chapter" data-level="1.6" data-path="introduction.html"><a href="introduction.html#kotlin-setup"><i class="fa fa-check"></i><b>1.6</b> Kotlin</a></li>
</ul></li>
<li class="chapter" data-level="2" data-path="resources-and-layouts.html"><a href="resources-and-layouts.html"><i class="fa fa-check"></i><b>2</b> Resources and Layouts</a><ul>
<li class="chapter" data-level="2.1" data-path="resources-and-layouts.html"><a href="resources-and-layouts.html#resources"><i class="fa fa-check"></i><b>2.1</b> Resources</a><ul>
<li class="chapter" data-level="" data-path="resources-and-layouts.html"><a href="resources-and-layouts.html#r"><i class="fa fa-check"></i>R</a></li>
<li class="chapter" data-level="" data-path="resources-and-layouts.html"><a href="resources-and-layouts.html#alternative-resources"><i class="fa fa-check"></i>Alternative Resources</a></li>
</ul></li>
<li class="chapter" data-level="2.2" data-path="resources-and-layouts.html"><a href="resources-and-layouts.html#views"><i class="fa fa-check"></i><b>2.2</b> Views</a><ul>
<li class="chapter" data-level="" data-path="resources-and-layouts.html"><a href="resources-and-layouts.html#view-properties"><i class="fa fa-check"></i>View Properties</a></li>
<li class="chapter" data-level="" data-path="resources-and-layouts.html"><a href="resources-and-layouts.html#views-and-java"><i class="fa fa-check"></i>Views and Java</a></li>
<li class="chapter" data-level="" data-path="resources-and-layouts.html"><a href="resources-and-layouts.html#practice"><i class="fa fa-check"></i>Practice</a></li>
</ul></li>
<li class="chapter" data-level="2.3" data-path="resources-and-layouts.html"><a href="resources-and-layouts.html#layouts"><i class="fa fa-check"></i><b>2.3</b> Layouts</a><ul>
<li class="chapter" data-level="" data-path="resources-and-layouts.html"><a href="resources-and-layouts.html#linearlayout"><i class="fa fa-check"></i>LinearLayout</a></li>
<li class="chapter" data-level="" data-path="resources-and-layouts.html"><a href="resources-and-layouts.html#relativelayout"><i class="fa fa-check"></i>RelativeLayout</a></li>
<li class="chapter" data-level="" data-path="resources-and-layouts.html"><a href="resources-and-layouts.html#constraintlayout"><i class="fa fa-check"></i>ConstraintLayout</a></li>
<li class="chapter" data-level="" data-path="resources-and-layouts.html"><a href="resources-and-layouts.html#other-layouts"><i class="fa fa-check"></i>Other Layouts</a></li>
<li class="chapter" data-level="" data-path="resources-and-layouts.html"><a href="resources-and-layouts.html#combining-and-inflating-layouts"><i class="fa fa-check"></i>Combining and Inflating Layouts</a></li>
</ul></li>
<li class="chapter" data-level="2.4" data-path="resources-and-layouts.html"><a href="resources-and-layouts.html#inputs"><i class="fa fa-check"></i><b>2.4</b> Inputs</a></li>
</ul></li>
<li class="chapter" data-level="3" data-path="activities.html"><a href="activities.html"><i class="fa fa-check"></i><b>3</b> Activities</a><ul>
<li class="chapter" data-level="3.1" data-path="activities.html"><a href="activities.html#making-activities"><i class="fa fa-check"></i><b>3.1</b> Making Activities</a></li>
<li class="chapter" data-level="3.2" data-path="activities.html"><a href="activities.html#the-activity-lifecycle"><i class="fa fa-check"></i><b>3.2</b> The Activity Lifecycle</a><ul>
<li class="chapter" data-level="" data-path="activities.html"><a href="activities.html#overriding-the-callback-methods"><i class="fa fa-check"></i>Overriding the Callback Methods</a></li>
<li class="chapter" data-level="" data-path="activities.html"><a href="activities.html#saving-and-restoring-activity-state"><i class="fa fa-check"></i>Saving and Restoring Activity State</a></li>
</ul></li>
<li class="chapter" data-level="3.3" data-path="activities.html"><a href="activities.html#context"><i class="fa fa-check"></i><b>3.3</b> Context</a></li>
<li class="chapter" data-level="3.4" data-path="activities.html"><a href="activities.html#multiple-activities"><i class="fa fa-check"></i><b>3.4</b> Multiple Activities</a><ul>
<li class="chapter" data-level="" data-path="activities.html"><a href="activities.html#activity-intents"><i class="fa fa-check"></i>Intents</a></li>
<li class="chapter" data-level="" data-path="activities.html"><a href="activities.html#back-tasks"><i class="fa fa-check"></i>Back & Tasks</a></li>
<li class="chapter" data-level="" data-path="activities.html"><a href="activities.html#up-navigation"><i class="fa fa-check"></i>Up Navigation</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="4" data-path="data-views.html"><a href="data-views.html"><i class="fa fa-check"></i><b>4</b> Data-Driven Views</a><ul>
<li class="chapter" data-level="4.1" data-path="data-views.html"><a href="data-views.html#listviews-and-adapters"><i class="fa fa-check"></i><b>4.1</b> ListViews and Adapters</a></li>
<li class="chapter" data-level="4.2" data-path="data-views.html"><a href="data-views.html#networking-with-volley"><i class="fa fa-check"></i><b>4.2</b> Networking with Volley</a><ul>
<li class="chapter" data-level="" data-path="data-views.html"><a href="data-views.html#using-volley"><i class="fa fa-check"></i>Using Volley</a></li>
<li class="chapter" data-level="" data-path="data-views.html"><a href="data-views.html#requestqueue-singletons"><i class="fa fa-check"></i>RequestQueue Singletons</a></li>
<li class="chapter" data-level="" data-path="data-views.html"><a href="data-views.html#downloading-images"><i class="fa fa-check"></i>Downloading Images</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="5" data-path="material-design.html"><a href="material-design.html"><i class="fa fa-check"></i><b>5</b> Material Design</a><ul>
<li class="chapter" data-level="5.1" data-path="material-design.html"><a href="material-design.html#the-material-design-language"><i class="fa fa-check"></i><b>5.1</b> The Material Design Language</a></li>
<li class="chapter" data-level="5.2" data-path="material-design.html"><a href="material-design.html#material-styles-icons"><i class="fa fa-check"></i><b>5.2</b> Material Styles & Icons</a></li>
<li class="chapter" data-level="5.3" data-path="material-design.html"><a href="material-design.html#design-support-libraries"><i class="fa fa-check"></i><b>5.3</b> Design Support Libraries</a><ul>
<li class="chapter" data-level="" data-path="material-design.html"><a href="material-design.html#widgets"><i class="fa fa-check"></i>Widgets</a></li>
<li class="chapter" data-level="" data-path="material-design.html"><a href="material-design.html#coordinator-layout"><i class="fa fa-check"></i>Coordinator Layout</a></li>
</ul></li>
<li class="chapter" data-level="5.4" data-path="material-design.html"><a href="material-design.html#animations"><i class="fa fa-check"></i><b>5.4</b> Animations</a></li>
<li class="chapter" data-level="" data-path="material-design.html"><a href="material-design.html#resources-1"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="6" data-path="fragments.html"><a href="fragments.html"><i class="fa fa-check"></i><b>6</b> Fragments</a><ul>
<li class="chapter" data-level="6.1" data-path="fragments.html"><a href="fragments.html#creating-a-fragment"><i class="fa fa-check"></i><b>6.1</b> Creating a Fragment</a><ul>
<li class="chapter" data-level="" data-path="fragments.html"><a href="fragments.html#activity-to-fragment-communication"><i class="fa fa-check"></i>Activity-to-Fragment Communication</a></li>
</ul></li>
<li class="chapter" data-level="6.2" data-path="fragments.html"><a href="fragments.html#dynamic-fragments"><i class="fa fa-check"></i><b>6.2</b> Dynamic Fragments</a><ul>
<li class="chapter" data-level="" data-path="fragments.html"><a href="fragments.html#instantiating-fragments"><i class="fa fa-check"></i>Instantiating Fragments</a></li>
<li class="chapter" data-level="" data-path="fragments.html"><a href="fragments.html#transactions"><i class="fa fa-check"></i>Transactions</a></li>
<li class="chapter" data-level="" data-path="fragments.html"><a href="fragments.html#inter-fragment-communication"><i class="fa fa-check"></i>Inter-Fragment Communication</a></li>
<li class="chapter" data-level="" data-path="fragments.html"><a href="fragments.html#the-back-stack"><i class="fa fa-check"></i>The Back Stack</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="7" data-path="intents.html"><a href="intents.html"><i class="fa fa-check"></i><b>7</b> Intents</a><ul>
<li class="chapter" data-level="7.1" data-path="intents.html"><a href="intents.html#intents-for-another-activity-explicit"><i class="fa fa-check"></i><b>7.1</b> Intents for Another Activity (Explicit)</a><ul>
<li class="chapter" data-level="" data-path="intents.html"><a href="intents.html#extras"><i class="fa fa-check"></i>Extras</a></li>
</ul></li>
<li class="chapter" data-level="7.2" data-path="intents.html"><a href="intents.html#intents-for-another-app-implicit"><i class="fa fa-check"></i><b>7.2</b> Intents for Another App (Implicit)</a></li>
<li class="chapter" data-level="7.3" data-path="intents.html"><a href="intents.html#intents-for-a-response"><i class="fa fa-check"></i><b>7.3</b> Intents for a Response</a></li>
<li class="chapter" data-level="7.4" data-path="intents.html"><a href="intents.html#listening-for-intents"><i class="fa fa-check"></i><b>7.4</b> Listening for Intents</a></li>
<li class="chapter" data-level="7.5" data-path="intents.html"><a href="intents.html#broadcasts-and-receivers"><i class="fa fa-check"></i><b>7.5</b> Broadcasts and Receivers</a></li>
<li class="chapter" data-level="7.6" data-path="intents.html"><a href="intents.html#menus"><i class="fa fa-check"></i><b>7.6</b> Menus</a><ul>
<li class="chapter" data-level="" data-path="intents.html"><a href="intents.html#action-views"><i class="fa fa-check"></i>Action Views</a></li>
<li class="chapter" data-level="" data-path="intents.html"><a href="intents.html#context-menus"><i class="fa fa-check"></i>Context Menus</a></li>
</ul></li>
<li class="chapter" data-level="7.7" data-path="intents.html"><a href="intents.html#an-intent-example-sms"><i class="fa fa-check"></i><b>7.7</b> An Intent Example: SMS</a></li>
</ul></li>
<li class="chapter" data-level="8" data-path="notifications-settings.html"><a href="notifications-settings.html"><i class="fa fa-check"></i><b>8</b> Notifications & Settings</a><ul>
<li class="chapter" data-level="8.1" data-path="notifications-settings.html"><a href="notifications-settings.html#dialogs"><i class="fa fa-check"></i><b>8.1</b> Dialogs</a><ul>
<li class="chapter" data-level="" data-path="notifications-settings.html"><a href="notifications-settings.html#dialogfragments"><i class="fa fa-check"></i>DialogFragments</a></li>
</ul></li>
<li class="chapter" data-level="8.2" data-path="notifications-settings.html"><a href="notifications-settings.html#notifications"><i class="fa fa-check"></i><b>8.2</b> Notifications</a><ul>
<li class="chapter" data-level="8.2.1" data-path="notifications-settings.html"><a href="notifications-settings.html#tap-actions"><i class="fa fa-check"></i><b>8.2.1</b> Tap Actions</a></li>
</ul></li>
<li class="chapter" data-level="8.3" data-path="notifications-settings.html"><a href="notifications-settings.html#settings"><i class="fa fa-check"></i><b>8.3</b> Settings</a><ul>
<li class="chapter" data-level="" data-path="notifications-settings.html"><a href="notifications-settings.html#sharedpreferences"><i class="fa fa-check"></i>SharedPreferences</a></li>
<li class="chapter" data-level="" data-path="notifications-settings.html"><a href="notifications-settings.html#preference-settings"><i class="fa fa-check"></i>Preference Settings</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="9" data-path="loaders.html"><a href="loaders.html"><i class="fa fa-check"></i><b>9</b> Providers and Loaders</a><ul>
<li class="chapter" data-level="9.1" data-path="loaders.html"><a href="loaders.html#content-providers-intro"><i class="fa fa-check"></i><b>9.1</b> Content Providers</a></li>
<li class="chapter" data-level="9.2" data-path="loaders.html"><a href="loaders.html#cursors"><i class="fa fa-check"></i><b>9.2</b> Cursors</a></li>
<li class="chapter" data-level="9.3" data-path="loaders.html"><a href="loaders.html#loaders"><i class="fa fa-check"></i><b>9.3</b> Loaders</a></li>
<li class="chapter" data-level="9.4" data-path="loaders.html"><a href="loaders.html#other-provider-actions"><i class="fa fa-check"></i><b>9.4</b> Other Provider Actions</a></li>
</ul></li>
<li class="chapter" data-level="10" data-path="files-and-permissions.html"><a href="files-and-permissions.html"><i class="fa fa-check"></i><b>10</b> Files and Permissions</a><ul>
<li class="chapter" data-level="10.1" data-path="files-and-permissions.html"><a href="files-and-permissions.html#file-storage-locations"><i class="fa fa-check"></i><b>10.1</b> File Storage Locations</a></li>
<li class="chapter" data-level="10.2" data-path="files-and-permissions.html"><a href="files-and-permissions.html#permissions"><i class="fa fa-check"></i><b>10.2</b> Permissions</a></li>
<li class="chapter" data-level="10.3" data-path="files-and-permissions.html"><a href="files-and-permissions.html#external-storage"><i class="fa fa-check"></i><b>10.3</b> External Storage</a></li>
<li class="chapter" data-level="10.4" data-path="files-and-permissions.html"><a href="files-and-permissions.html#internal-storage-cache"><i class="fa fa-check"></i><b>10.4</b> Internal Storage & Cache</a></li>
<li class="chapter" data-level="10.5" data-path="files-and-permissions.html"><a href="files-and-permissions.html#example-saving-pictures"><i class="fa fa-check"></i><b>10.5</b> Example: Saving Pictures</a><ul>
<li class="chapter" data-level="10.5.1" data-path="files-and-permissions.html"><a href="files-and-permissions.html#fileproviders"><i class="fa fa-check"></i><b>10.5.1</b> FileProviders</a></li>
</ul></li>
<li class="chapter" data-level="10.6" data-path="files-and-permissions.html"><a href="files-and-permissions.html#sharing-files"><i class="fa fa-check"></i><b>10.6</b> Sharing Files</a></li>
</ul></li>
<li class="chapter" data-level="11" data-path="databases.html"><a href="databases.html"><i class="fa fa-check"></i><b>11</b> Providers and Databases</a><ul>
<li class="chapter" data-level="11.1" data-path="databases.html"><a href="databases.html#review-providers-and-loaders"><i class="fa fa-check"></i><b>11.1</b> Review: Providers and Loaders</a></li>
<li class="chapter" data-level="11.2" data-path="databases.html"><a href="databases.html#sqlite-databases"><i class="fa fa-check"></i><b>11.2</b> SQLite Databases</a></li>
<li class="chapter" data-level="11.3" data-path="databases.html"><a href="databases.html#implementing-a-contentprovider"><i class="fa fa-check"></i><b>11.3</b> Implementing a ContentProvider</a><ul>
<li class="chapter" data-level="" data-path="databases.html"><a href="databases.html#uris-and-types"><i class="fa fa-check"></i>URIs and Types</a></li>
<li class="chapter" data-level="" data-path="databases.html"><a href="databases.html#query-methods"><i class="fa fa-check"></i>Query Methods</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="12" data-path="location.html"><a href="location.html"><i class="fa fa-check"></i><b>12</b> Location</a><ul>
<li class="chapter" data-level="12.1" data-path="location.html"><a href="location.html#localization-techniques"><i class="fa fa-check"></i><b>12.1</b> Localization Techniques</a><ul>
<li class="chapter" data-level="" data-path="location.html"><a href="location.html#gps"><i class="fa fa-check"></i>GPS</a></li>
<li class="chapter" data-level="" data-path="location.html"><a href="location.html#cell-tower-localization"><i class="fa fa-check"></i>Cell Tower Localization</a></li>
<li class="chapter" data-level="" data-path="location.html"><a href="location.html#wifi-localization"><i class="fa fa-check"></i>WiFi Localization</a></li>
<li class="chapter" data-level="" data-path="location.html"><a href="location.html#representing-location"><i class="fa fa-check"></i>Representing Location</a></li>
</ul></li>
<li class="chapter" data-level="12.2" data-path="location.html"><a href="location.html#android-location"><i class="fa fa-check"></i><b>12.2</b> Android Location</a><ul>
<li class="chapter" data-level="" data-path="location.html"><a href="location.html#google-play-services"><i class="fa fa-check"></i>Google Play Services</a></li>
<li class="chapter" data-level="" data-path="location.html"><a href="location.html#accessing-location"><i class="fa fa-check"></i>Accessing Location</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="13" data-path="services.html"><a href="services.html"><i class="fa fa-check"></i><b>13</b> Threads and Services</a><ul>
<li class="chapter" data-level="13.1" data-path="services.html"><a href="services.html#threads-and-processes"><i class="fa fa-check"></i><b>13.1</b> Threads and Processes</a><ul>
<li class="chapter" data-level="" data-path="services.html"><a href="services.html#java-threads"><i class="fa fa-check"></i>Java Threads</a></li>
<li class="chapter" data-level="" data-path="services.html"><a href="services.html#android-threads"><i class="fa fa-check"></i>Android Threads</a></li>
</ul></li>
<li class="chapter" data-level="13.2" data-path="services.html"><a href="services.html#intentservices"><i class="fa fa-check"></i><b>13.2</b> IntentServices</a><ul>
<li class="chapter" data-level="" data-path="services.html"><a href="services.html#the-service-lifecycle"><i class="fa fa-check"></i>The Service Lifecycle</a></li>
</ul></li>
<li class="chapter" data-level="13.3" data-path="services.html"><a href="services.html#example-a-music-service"><i class="fa fa-check"></i><b>13.3</b> Example: A Music Service</a><ul>
<li class="chapter" data-level="" data-path="services.html"><a href="services.html#mediaplayer"><i class="fa fa-check"></i>MediaPlayer</a></li>
<li class="chapter" data-level="" data-path="services.html"><a href="services.html#creating-a-service"><i class="fa fa-check"></i>Creating a Service</a></li>
</ul></li>
<li class="chapter" data-level="13.4" data-path="services.html"><a href="services.html#foreground-services"><i class="fa fa-check"></i><b>13.4</b> Foreground Services</a></li>
<li class="chapter" data-level="13.5" data-path="services.html"><a href="services.html#bound-services"><i class="fa fa-check"></i><b>13.5</b> Bound Services</a></li>
</ul></li>
<li class="chapter" data-level="14" data-path="sensors.html"><a href="sensors.html"><i class="fa fa-check"></i><b>14</b> Sensors</a><ul>
<li class="chapter" data-level="14.1" data-path="sensors.html"><a href="sensors.html#motion-sensors"><i class="fa fa-check"></i><b>14.1</b> Motion Sensors</a><ul>
<li class="chapter" data-level="" data-path="sensors.html"><a href="sensors.html#accessing-sensors"><i class="fa fa-check"></i>Accessing Sensors</a></li>
<li class="chapter" data-level="" data-path="sensors.html"><a href="sensors.html#composite-sensors"><i class="fa fa-check"></i>Composite Sensors</a></li>
</ul></li>
<li class="chapter" data-level="14.2" data-path="sensors.html"><a href="sensors.html#rotation"><i class="fa fa-check"></i><b>14.2</b> Rotation</a><ul>
<li class="chapter" data-level="" data-path="sensors.html"><a href="sensors.html#coordinates"><i class="fa fa-check"></i>Coordinates</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="15" data-path="graphics.html"><a href="graphics.html"><i class="fa fa-check"></i><b>15</b> Graphics and Touch</a><ul>
<li class="chapter" data-level="15.1" data-path="graphics.html"><a href="graphics.html#drawing-graphics"><i class="fa fa-check"></i><b>15.1</b> Drawing Graphics</a><ul>
<li class="chapter" data-level="" data-path="graphics.html"><a href="graphics.html#custom-views"><i class="fa fa-check"></i>Custom Views</a></li>
<li class="chapter" data-level="" data-path="graphics.html"><a href="graphics.html#surfaceviews"><i class="fa fa-check"></i>SurfaceViews</a></li>
</ul></li>
<li class="chapter" data-level="15.2" data-path="graphics.html"><a href="graphics.html#touch-and-gestures"><i class="fa fa-check"></i><b>15.2</b> Touch and Gestures</a><ul>
<li class="chapter" data-level="" data-path="graphics.html"><a href="graphics.html#advanced-gestures"><i class="fa fa-check"></i>Advanced Gestures</a></li>
</ul></li>
<li class="chapter" data-level="15.3" data-path="graphics.html"><a href="graphics.html#property-animation"><i class="fa fa-check"></i><b>15.3</b> Property Animation</a></li>
</ul></li>
<li class="part"><span><b>II Additional Topics (Labs)</b></span></li>
<li class="chapter" data-level="16" data-path="styles-themes.html"><a href="styles-themes.html"><i class="fa fa-check"></i><b>16</b> Styles & Themes</a><ul>
<li class="chapter" data-level="16.1" data-path="styles-themes.html"><a href="styles-themes.html#defining-styles"><i class="fa fa-check"></i><b>16.1</b> Defining Styles</a><ul>
<li class="chapter" data-level="" data-path="styles-themes.html"><a href="styles-themes.html#style-inheritance"><i class="fa fa-check"></i>Style Inheritance</a></li>
<li class="chapter" data-level="" data-path="styles-themes.html"><a href="styles-themes.html#built-in-styles"><i class="fa fa-check"></i>Built-in Styles</a></li>
<li class="chapter" data-level="" data-path="styles-themes.html"><a href="styles-themes.html#styles-for-text-views"><i class="fa fa-check"></i>Styles for Text Views</a></li>
</ul></li>
<li class="chapter" data-level="16.2" data-path="styles-themes.html"><a href="styles-themes.html#themes"><i class="fa fa-check"></i><b>16.2</b> Themes</a><ul>
<li class="chapter" data-level="" data-path="styles-themes.html"><a href="styles-themes.html#material-themes"><i class="fa fa-check"></i>Material Themes</a></li>
<li class="chapter" data-level="" data-path="styles-themes.html"><a href="styles-themes.html#theme-attributes"><i class="fa fa-check"></i>Theme Attributes</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="styles-themes.html"><a href="styles-themes.html#resources-2"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="17" data-path="fragment-viewpager.html"><a href="fragment-viewpager.html"><i class="fa fa-check"></i><b>17</b> Fragments: ViewPager</a><ul>
<li class="chapter" data-level="17.1" data-path="fragment-viewpager.html"><a href="fragment-viewpager.html#define-a-searchfragment"><i class="fa fa-check"></i><b>17.1</b> Define a SearchFragment</a></li>
<li class="chapter" data-level="17.2" data-path="fragment-viewpager.html"><a href="fragment-viewpager.html#add-the-viewpager-and-adapter"><i class="fa fa-check"></i><b>17.2</b> Add the ViewPager and Adapter</a></li>
<li class="chapter" data-level="17.3" data-path="fragment-viewpager.html"><a href="fragment-viewpager.html#add-user-interaction"><i class="fa fa-check"></i><b>17.3</b> Add User Interaction</a></li>
</ul></li>
<li class="chapter" data-level="18" data-path="bluetooth.html"><a href="bluetooth.html"><i class="fa fa-check"></i><b>18</b> Bluetooth</a></li>
<li class="chapter" data-level="19" data-path="maps.html"><a href="maps.html"><i class="fa fa-check"></i><b>19</b> Maps</a><ul>
<li class="chapter" data-level="19.1" data-path="maps.html"><a href="maps.html#create-a-map-activity"><i class="fa fa-check"></i><b>19.1</b> Create a Map Activity</a><ul>
<li class="chapter" data-level="" data-path="maps.html"><a href="maps.html#getting-an-api-key"><i class="fa fa-check"></i>Getting an API Key</a></li>
<li><a href="maps.html#the-supportmapfragment">The <code>SupportMapFragment</code></a></li>
</ul></li>
<li class="chapter" data-level="19.2" data-path="maps.html"><a href="maps.html#specifying-the-user-interface"><i class="fa fa-check"></i><b>19.2</b> Specifying the User Interface</a></li>
<li class="chapter" data-level="19.3" data-path="maps.html"><a href="maps.html#markers-and-drawings"><i class="fa fa-check"></i><b>19.3</b> Markers and Drawings</a><ul>
<li class="chapter" data-level="" data-path="maps.html"><a href="maps.html#drawing-shapes"><i class="fa fa-check"></i>Drawing Shapes</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="20" data-path="memory.html"><a href="memory.html"><i class="fa fa-check"></i><b>20</b> Memory Management</a><ul>
<li class="chapter" data-level="20.1" data-path="memory.html"><a href="memory.html#memory-allocation"><i class="fa fa-check"></i><b>20.1</b> Memory Allocation</a></li>
<li class="chapter" data-level="20.2" data-path="memory.html"><a href="memory.html#the-memory-monitor"><i class="fa fa-check"></i><b>20.2</b> The Memory Monitor</a><ul>
<li class="chapter" data-level="" data-path="memory.html"><a href="memory.html#garbage-collection"><i class="fa fa-check"></i>Garbage Collection</a></li>
</ul></li>
<li class="chapter" data-level="20.3" data-path="memory.html"><a href="memory.html#memory-leaks"><i class="fa fa-check"></i><b>20.3</b> Memory Leaks</a></li>
</ul></li>
<li class="chapter" data-level="21" data-path="multi-touch.html"><a href="multi-touch.html"><i class="fa fa-check"></i><b>21</b> Multi-Touch</a><ul>
<li class="chapter" data-level="21.1" data-path="multi-touch.html"><a href="multi-touch.html#identifying-fingers"><i class="fa fa-check"></i><b>21.1</b> Identifying Fingers</a></li>
<li class="chapter" data-level="21.2" data-path="multi-touch.html"><a href="multi-touch.html#drawing-touches"><i class="fa fa-check"></i><b>21.2</b> Drawing Touches</a></li>
<li class="chapter" data-level="21.3" data-path="multi-touch.html"><a href="multi-touch.html#moving-fingers"><i class="fa fa-check"></i><b>21.3</b> Moving Fingers</a></li>
<li class="chapter" data-level="21.4" data-path="multi-touch.html"><a href="multi-touch.html#other-multi-touch-gestures"><i class="fa fa-check"></i><b>21.4</b> Other Multi-Touch Gestures</a></li>
</ul></li>
<li class="appendix"><span><b>Appendix</b></span></li>
<li class="chapter" data-level="A" data-path="java-review.html"><a href="java-review.html"><i class="fa fa-check"></i><b>A</b> Java Review</a><ul>
<li class="chapter" data-level="A.1" data-path="java-review.html"><a href="java-review.html#building-apps-with-gradle"><i class="fa fa-check"></i><b>A.1</b> Building Apps with Gradle</a></li>
<li class="chapter" data-level="A.2" data-path="java-review.html"><a href="java-review.html#class-basics"><i class="fa fa-check"></i><b>A.2</b> Class Basics</a></li>
<li class="chapter" data-level="A.3" data-path="java-review.html"><a href="java-review.html#inheritance"><i class="fa fa-check"></i><b>A.3</b> Inheritance</a></li>
<li class="chapter" data-level="A.4" data-path="java-review.html"><a href="java-review.html#interfaces"><i class="fa fa-check"></i><b>A.4</b> Interfaces</a></li>
<li class="chapter" data-level="A.5" data-path="java-review.html"><a href="java-review.html#polymorphism"><i class="fa fa-check"></i><b>A.5</b> Polymorphism</a></li>
<li class="chapter" data-level="A.6" data-path="java-review.html"><a href="java-review.html#abstract-methods-and-classes"><i class="fa fa-check"></i><b>A.6</b> Abstract Methods and Classes</a></li>
<li class="chapter" data-level="A.7" data-path="java-review.html"><a href="java-review.html#generics"><i class="fa fa-check"></i><b>A.7</b> Generics</a></li>
<li class="chapter" data-level="A.8" data-path="java-review.html"><a href="java-review.html#nested-classes"><i class="fa fa-check"></i><b>A.8</b> Nested Classes</a></li>
</ul></li>
<li class="chapter" data-level="B" data-path="java-swing.html"><a href="java-swing.html"><i class="fa fa-check"></i><b>B</b> Java Swing Framework</a><ul>
<li class="chapter" data-level="B.1" data-path="java-swing.html"><a href="java-swing.html#events"><i class="fa fa-check"></i><b>B.1</b> Events</a></li>
<li class="chapter" data-level="B.2" data-path="java-swing.html"><a href="java-swing.html#layouts-and-composites"><i class="fa fa-check"></i><b>B.2</b> Layouts and Composites</a></li>
</ul></li>
<li class="chapter" data-level="C" data-path="publishing.html"><a href="publishing.html"><i class="fa fa-check"></i><b>C</b> Publishing</a><ul>
<li class="chapter" data-level="C.1" data-path="publishing.html"><a href="publishing.html#signing-an-app"><i class="fa fa-check"></i><b>C.1</b> Signing an App</a><ul>
<li><a href="publishing.html#release-.apk">Release <code>.apk</code></a></li>
</ul></li>
</ul></li>
<li class="divider"></li>
<li><a href="https://github.com/rstudio/bookdown" target="blank">Published with bookdown</a></li>
</ul>
</nav>
</div>
<div class="book-body">
<div class="body-inner">
<div class="book-header" role="navigation">
<h1>
<i class="fa fa-circle-o-notch fa-spin"></i><a href="./">Android Development: Lecture Notes</a>
</h1>
</div>
<div class="page-wrapper" tabindex="-1" role="main">
<div class="page-inner">
<section class="normal" id="section-">
<div id="intents" class="section level1">
<h1><span class="header-section-number">Lecture 7</span> Intents</h1>
<p>This lecture discusses how to use <a href="https://developer.android.com/guide/components/intents-filters.html"><strong>Intents</strong></a> to communicate between different Activities and Applications. The Intent system allows Activities to communicate, even though they don’t have references to each other (and thus we can’t just call a method on them).</p>
<p class="alert alert-info">
This lecture references code found at <a href="https://github.com/info448/lecture07-intents" class="uri">https://github.com/info448/lecture07-intents</a>. Note that you will need to have a working camera on your device for this demo. To enable the camera in the emulator, use the <code>Tools > Android > AVD</code> menu to modify the emulator, and select “webcam” for the front camera option. Confirm that it is enabled by launching the Camera app.
</p>
<!-- Formatted, but not edited for content -->
<p>An Intent is a <strong>message</strong> that is sent between app components, allowing them to communicate!</p>
<ul>
<li><p>Most object communication we do is via <em>direct method call</em>; you have a reference to an Object and then you call a method on it. We’ve also seen <em>event callbacks</em>, where on an event one of our callbacks gets executed by the system—but this is really just a wrapper around <em>direct method call</em> via the Observer pattern.</p></li>
<li><p>Intents work a bit differently: they allow us to create an object that can be “given” to another component (read: Activity), who can then respond upon receiving it. This is similar to an event callback, but working at a slightly higher system level.</p></li>
</ul>
<p>Intents were previously introduced in <a href="activities.html#activity-intents">Lecture 3</a>. But to reiterate: you can think of Intents as like letters you’d send through the mail: they are addressed to a particular target (e.g., another Activity—more properly a <code>Context</code>), and have room for some data called <strong>extras</strong> to go inside (held in a <code>Bundle</code>). When the envelope arrives, the recipient can get that data out and do something with it… and possibly send a response back.</p>
<p>Note that there are couple of different kinds of Intents; we’ll go through examples of each.</p>
<div id="intents-for-another-activity-explicit" class="section level2">
<h2><span class="header-section-number">7.1</span> Intents for Another Activity (Explicit)</h2>
<p>The most basic kind of Intent is an Intent sent to a specific Activity/Context, such as for telling that Activity to open. This was the same type of Intent introduced in Lecture 3.</p>
<div class="sourceCode"><pre class="sourceCode java"><code class="sourceCode java"><span class="co">//java</span>
<span class="co">// context, target</span>
Intent intent = <span class="kw">new</span> <span class="fu">Intent</span>(MainActivity.<span class="fu">this</span>, SecondActivity.<span class="fu">class</span>);
<span class="fu">startActivity</span>(intent);</code></pre></div>
<div class="sourceCode"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><span class="co">//kotlin</span>
<span class="co">// context, target</span>
<span class="kw">val</span> <span class="va">intent</span> = Intent(this<span class="at">@MainActivity</span>, SecondActivity::<span class="kw">class</span>.java)</code></pre></div>
<p>We instantiate the Intent (specifying the <code>Context</code>it should be delivered from and the <code>Class</code> it should be delivered to), and then use that message to start an Activity by delivering the Intent via the <code>startActivity()</code> method.</p>
<ul>
<li>The <code>startActivity()</code> method effectively means “this is an Intent used to launch an Activity: whoever receives this Intent should start!” You can almost think of it as saying that the letters should be delivered to the “start activity” mailbox.</li>
</ul>
<p>This type of Intent is called an <strong>Explicit Intent</strong> because we’re <em>explicit</em> about what target we want to receive it. It’s a letter to a specific Activity.</p>
<div id="extras" class="section level3 unnumbered">
<h3>Extras</h3>
<p>We can also specify some extra data inside our envelope. These data are referred to as <strong>Extras</strong>. This is a <code>Bundle</code> (a set of primitive key-value pairs) that we can use to pass <em>limited</em> information around!</p>
<div class="sourceCode"><pre class="sourceCode java"><code class="sourceCode java">intent.<span class="fu">putExtra</span>(<span class="st">"package.name.key"</span>, <span class="st">"value"</span>);</code></pre></div>
<ul>
<li>The Android documentation notes that best practice is to include the full package name in Bundle keys, so avoid any collisions or misreading of data (since Intents can move outside of the Application). There are also some pre-defined key values (constants) that you can and will use in the <code>Intent</code> class.</li>
</ul>
<p>We can then get the extras from the Intent in the Activity that receives it:</p>
<div class="sourceCode"><pre class="sourceCode java"><code class="sourceCode java"><span class="co">//java</span>
<span class="co">//in onCreate()</span>
Bundle extras = <span class="fu">getIntent</span>().<span class="fu">getExtras</span>(); <span class="co">//All activities are started with an Intent!</span>
<span class="bu">String</span> value = extras.<span class="fu">getString</span>(<span class="st">"key"</span>);</code></pre></div>
<div class="sourceCode"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><span class="co">//kotlin</span>
<span class="kw">val</span> <span class="va">extras</span> = intent.extras <span class="co">//All Activities are started with an Intent! (so have that property)</span>
<span class="kw">val</span> <span class="va">value</span> = extras.getString(<span class="st">"key"</span>)</code></pre></div>
<p>So we can have Activities communicate, and even share information between them! Yay!</p>
</div>
</div>
<div id="intents-for-another-app-implicit" class="section level2">
<h2><span class="header-section-number">7.2</span> Intents for Another App (Implicit)</h2>
<p>We can send Intents to our own Activities, but we can also address them to <em>other</em> applications. When calling on other apps, we usually use an <strong>Implicit Intent</strong>.</p>
<ul>
<li>This is a little bit like letters that have <a href="http://www.theguardian.com/world/2015/jul/18/postman-turns-detective-to-deliver-letter-with-cryptic-address-in-ireland">weird addresses</a>, but still get delivered. “For that guy at the end of the block with the red mailbox.”</li>
</ul>
<p>An Implicit Intent includes an <strong>Action</strong> and some <strong>Data</strong>. The <strong><em>Action</em></strong> says what the target should <em>do</em> with the intent (a Command), and the <strong><em>Data</em></strong> gives more detail about what to run that action on.</p>
<ul>
<li><p><strong>Actions</strong> can be things like <code>ACTION_VIEW</code> to view some data, or <code>ACTION_PICK</code> to choose an item from a list. See a full list under <a href="https://developer.android.com/reference/android/content/Intent.html">“Standard Action Activities”</a><a href="#fn21" class="footnoteRef" id="fnref21"><sup>21</sup></a>.</p>
<ul>
<li><code>ACTION_MAIN</code> is the most common (just start the Activity as if it were a “main” launching point). So when we don’t specify anything else, this is used!</li>
</ul></li>
<li><p><strong>Data</strong> gives detail about what to do with the action (e.g., the Uri to <code>VIEW</code> or the Contact to <code>DIAL</code>).</p>
<ul>
<li>Extras then support this data!</li>
</ul></li>
</ul>
<p>For example, if we specify a <code>DIAL</code> action, then we’re saying that we want our Intent to be delivered to an application that is capable of dialing a telephone number.</p>
<ul>
<li><em>If there is more than one app that supports this action, the user will need to pick one!</em> This is key: we’re not saying exactly what app to use, just what kind of functionality we need to be supported! It’s a kind of abstraction!</li>
</ul>
<div class="sourceCode"><pre class="sourceCode java"><code class="sourceCode java"><span class="co">//java</span>
Intent intent = <span class="kw">new</span> <span class="fu">Intent</span>(Intent.<span class="fu">ACTION_DIAL</span>);
intent.<span class="fu">setData</span>(Uri.<span class="fu">parse</span>(<span class="st">"tel:206-685-1622"</span>));
<span class="kw">if</span> (intent.<span class="fu">resolveActivity</span>(<span class="fu">getPackageManager</span>()) != <span class="kw">null</span>) {
<span class="fu">startActivity</span>(intent);
}</code></pre></div>
<div class="sourceCode"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><span class="co">//kotlin</span>
<span class="kw">val</span> <span class="va">intent</span> = Intent(Intent.ACTION_DIAL)
intent.<span class="kw">data</span> = Uri.parse(<span class="st">"tel:206-685-1622"</span>)
<span class="cf">if</span> (intent.resolveActivity(packageManager) != <span class="kw">null</span>) {
startActivity(intent)
}</code></pre></div>
<p>Here we’ve specified the <em>Action</em> (<code>ACTION_DIAL</code>) for our Intent, as well as some <em>Data</em> (a phone number, converted into a Uri). The <code>resolveActivity()</code> method looks up what Activity is going to receive our action—we check that it’s not null before trying to start it up.</p>
<ul>
<li>This should allow us to “dial out” !</li>
</ul>
<p>Note that we can open up all sorts of apps. See <a href="https://developer.android.com/guide/components/intents-common.html">Common Intents</a><a href="#fn22" class="footnoteRef" id="fnref22"><sup>22</sup></a> for a list of common implicit events (with useful examples!).</p>
</div>
<div id="intents-for-a-response" class="section level2">
<h2><span class="header-section-number">7.3</span> Intents for a Response</h2>
<p>We’ve been using Intents to start Activities, but what if we’d like to get a result <em>back</em> from the Activity? That is, what if we want to look up a Contact or take a picture, and then be able to use the Contact’s number or show the picture?</p>
<p>To do this, we’re going to create Intents in the same way, but use a different method to launch them: <code>startActivityForResult()</code>. This will launch the resolved Activity. But once that Action is finished, the launched Activity will send <em>another</em> Intent back to us, which we can then react to in order to handle the result.</p>
<ul>
<li>This is a bit like including an “urgent, please respond!” note on the letter!</li>
</ul>
<p>For fun, let’s do it with the Camera—we’ll <a href="http://developer.android.com/training/camera/photobasics.html">launch the Camera</a> to take a picture, and then get the picture and show it in an <code>ImageView</code> we have.</p>
<ul>
<li>Note that your Emulator will need to have Camera emulation on!</li>
</ul>
<div class="sourceCode"><pre class="sourceCode java"><code class="sourceCode java"><span class="co">//java</span>
<span class="dt">static</span> <span class="dt">final</span> <span class="dt">int</span> REQUEST_IMAGE_CAPTURE = <span class="dv">1</span>;
<span class="kw">private</span> <span class="dt">void</span> <span class="fu">dispatchTakePictureIntent</span>() {
Intent takePictureIntent = <span class="kw">new</span> <span class="fu">Intent</span>(MediaStore.<span class="fu">ACTION_IMAGE_CAPTURE</span>);
<span class="kw">if</span> (takePictureIntent.<span class="fu">resolveActivity</span>(<span class="fu">getPackageManager</span>()) != <span class="kw">null</span>) {
<span class="fu">startActivityForResult</span>(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}</code></pre></div>
<div class="sourceCode"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><span class="co">//kotlin</span>
<span class="kw">private</span> <span class="kw">val</span> <span class="va">REQUEST_IMAGE_CAPTURE</span> = <span class="dv">1</span>
<span class="kw">fun</span> <span class="fu">dispatchTakePictureIntent</span>() {
<span class="kw">val</span> <span class="va">takePictureIntent</span> = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
<span class="cf">if</span> (takePictureIntent.resolveActivity(packageManager) != <span class="kw">null</span>) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
}
}</code></pre></div>
<ul>
<li><p>We start by specifying an Intent that uses the <code>MediaStore.ACTION_IMAGE_CAPTURE</code> action (the action for “take a still picture and return it”). We will then send this Intent for a result, similar to other Implicit Intents.</p></li>
<li><p>We also include a second argument: a “request code”. A request code is used to distinguish this Intent from others we may send (kind of like a tag). It let’s us know that the Result Intent (the “RSVP”) is for our “took a picture” letter, and not for some other Intent we sent.</p></li>
<li><p>Note that we could pass an Extra for where we want to save the large picture file to. However, we’re going to leave that off and just work with the thumbnail for this demonstration. See the <a href="http://developer.android.com/training/camera/photobasics.html#TaskPath">guide</a><a href="#fn23" class="footnoteRef" id="fnref23"><sup>23</sup></a> for details. This topic is also covered in a later chapter.</p></li>
</ul>
<p>In order to handle the “response” Intent, we need to provide a callback that will get executed when that Intent arrives. This callback is called <code>onActivityResult()</code>.</p>
<div class="sourceCode"><pre class="sourceCode java"><code class="sourceCode java"><span class="co">//java</span>
<span class="at">@Override</span>
<span class="kw">protected</span> <span class="dt">void</span> <span class="fu">onActivityResult</span>(<span class="dt">int</span> requestCode, <span class="dt">int</span> resultCode, Intent data) {
<span class="kw">if</span> (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.<span class="fu">getExtras</span>();
Bitmap imageBitmap = (Bitmap) extras.<span class="fu">get</span>(<span class="st">"data"</span>);
<span class="bu">ImageView</span> imageView = (<span class="bu">ImageView</span>) <span class="fu">findViewById</span>(R.<span class="fu">id</span>.<span class="fu">img_thumbnail</span>);
imageView.<span class="fu">setImageBitmap</span>(imageBitmap); <span class="co">//show the image</span>
}
}</code></pre></div>
<div class="sourceCode"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><span class="co">//kotlin</span>
<span class="kw">override</span> <span class="kw">fun</span> <span class="fu">onActivityResult</span>(<span class="va">requestCode</span>: <span class="dt">Int</span>, <span class="va">resultCode</span>: <span class="dt">Int</span>, <span class="kw">data</span>: <span class="dt">Intent</span>) {
<span class="cf">if</span> (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) {
<span class="kw">val</span> <span class="va">extras</span> = <span class="kw">data</span>.extras?.apply {
<span class="kw">val</span> <span class="va">imageBitmap</span> = <span class="kw">get</span>(<span class="st">"data"</span>) <span class="kw">as</span> Bitmap
<span class="kw">val</span> <span class="va">imageView</span> = findViewById<ImageView>(R.id.img_thumbnail)
imageView.setImageBitmap(imageBitmap)
}
}
}</code></pre></div>
<ul>
<li><p>We can get information about the Intent we’re receiving from the params, including which Intent led to the result (the <code>requestCode</code>) and the status of that request (the <code><em>result</em>Code</code>). We can get access to the returned data (e.g., the image) by getting the <code>"data"</code> value from the extras.</p></li>
<li><p>Note that this is a <a href="http://developer.android.com/reference/android/graphics/Bitmap.html"><code>Bitmap</code></a>, which is the Android class representing a raster image. We’ll play with Bitmaps more in a couple weeks, because I like graphics.</p></li>
</ul>
</div>
<div id="listening-for-intents" class="section level2">
<h2><span class="header-section-number">7.4</span> Listening for Intents</h2>
<p>We’re able to send implicit Intents that can be heard by other Apps, but what if we wanted to receive Implicit Intents ourselves? What if <em>we</em> want to be able to handle phone dialing?!</p>
<p>In order to receive an Implicit Intent, we need to declare that our Activity is able to handle that request. Since we’re specifying an aspect of our application (that other apps need to be aware of), we’ll do this in the <code>Manifest</code> using what is called an <strong><code><intent-filter></code></strong>.</p>
<ul>
<li>The idea is that we’re “hearing” all the intents, and we’re “filtering” for the ones that are relevant to us. Like sorting out the junk mail.</li>
</ul>
<p>An <code><intent-filter></code> tag is nested inside the element that it applies to (e.g., the <code><activity></code>). In fact, you can see there is already one there: that responds to the <code>MAIN</code> action sent with the <code>LAUNCHER</code> category (meaning that it responds to Intents from the app launcher).</p>
<p>Similarly, we can specify three “parts” of a filter:</p>
<ul>
<li><p>a <code><action android:name="action"></code> filter, which describes the Action we can respond to.</p></li>
<li><p>a <code><data ...></code> filter, which specifies aspects of the data we accept (e.g., only respond to Uri’s that look like telephone numbers)</p></li>
<li><p>a <code><category android:name="category"></code> filter, which is basically a “more information” piece. You can see the <a href="http://developer.android.com/reference/android/content/Intent.html">“Standard Categories”</a> in the documentation.</p></li>
<li><p>Note that you <em>must</em> include the <code>DEFAULT</code> category to receive Implicit Intents. This is the category used by <code>startActivity()</code> and <code>startActivityForResult()</code>.</p></li>
</ul>
<p>You can include multiple actions, data, and category tags. You just need to make sure that you can handle all possible combinations selected from each type (multiple types are combined with an “or”, not an “and”).</p>
<p>Responding to that dial command:</p>
<div class="sourceCode"><pre class="sourceCode xml"><code class="sourceCode xml"><span class="kw"><activity</span><span class="ot"> android:name=</span><span class="st">".SecondActivity"</span><span class="kw">></span>
<span class="kw"><intent-filter></span>
<span class="kw"><action</span><span class="ot"> android:name=</span><span class="st">"android.intent.action.DIAL"</span><span class="kw">/></span>
<span class="kw"><category</span><span class="ot"> android:name=</span><span class="st">"android.intent.category.DEFAULT"</span> <span class="kw">/></span>
<span class="kw"><data</span><span class="ot"> android:scheme=</span><span class="st">"tel"</span> <span class="kw">/></span> <span class="co"><!-- telephone Uris --></span>
<span class="kw"></intent-filter></span>
<span class="kw"></activity></span></code></pre></div>
<p>You can see many more examples in the <a href="http://developer.android.com/reference/android/content/Intent.html"><code>Intent</code></a> documentation.</p>
</div>
<div id="broadcasts-and-receivers" class="section level2">
<h2><span class="header-section-number">7.5</span> Broadcasts and Receivers</h2>
<p>There is one other kind of Intent I want to talk about today: <a href="http://developer.android.com/reference/android/content/BroadcastReceiver.html"><strong>Broadcasts</strong></a>. A broadcast is a message that <em>any</em> app can receive. Unlike Explicit and Implicit Intents, broadcasts are heard by the entire system—anything you “shout” with a broadcast is publicly available (so think about security concerns when using these!)</p>
<ul>
<li>To extend the snail mail metaphor, these are mass mailings perhaps.</li>
</ul>
<p>Other than who receives them, broadcasts work the same as normal Implicit Intents! We create an <code>Intent</code> with an Action and Data (and Category and Extras…). But instead of using the <code>startActivity()</code> method, we use the <code>sendBroadcast()</code> method. That Intent can now be heard by all <code>Activities</code> on the phone.</p>
<ul>
<li>We’ll skip a demo for lack of time and motivation… but we will generate broadcasts later in the course.</li>
</ul>
<p>For us, more common than sending broadcasts will be <em>receiving</em> broadcasts; that is, we want to listen and respond to System broadcasts that are produced (things like power events, wifi status, etc). This would also include listening for things like incoming phone calls or text messages!</p>
<p>We can receive broadcasts by using a <a href="http://developer.android.com/reference/android/content/BroadcastReceiver.html"><code>BroadcastReceiver</code></a>. This is a base class that is used by any class that can receive broadcast Intents. We <strong>subclass</strong> it and implement the <code>onReceive(Context, Intent)</code> callback in order to handle when broadcasts are received.</p>
<div class="sourceCode"><pre class="sourceCode java"><code class="sourceCode java"><span class="co">//java</span>
<span class="kw">public</span> <span class="dt">void</span> <span class="fu">onReceive</span>(<span class="bu">Context</span> context, Intent intent) {
Log.<span class="fu">v</span>(<span class="st">"TAG"</span>, <span class="st">"received! "</span>+intent.<span class="fu">toString</span>());
<span class="kw">if</span>(intent.<span class="fu">getAction</span>() == Intent.<span class="fu">ACTION_BATTERY_LOW</span>){
Toast.<span class="fu">makeText</span>(context, <span class="st">"Battery is low!"</span>, Toast.<span class="fu">LENGTH_SHORT</span>).<span class="fu">show</span>();
}
}</code></pre></div>
<div class="sourceCode"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><span class="co">//kotlin</span>
<span class="kw">override</span> <span class="kw">fun</span> <span class="fu">onReceive</span>(<span class="va">context</span>: <span class="dt">Context</span>, <span class="va">intent</span>: <span class="dt">Intent</span>) {
Log.v(<span class="st">"TAG"</span>, <span class="st">"received! ${intent.toString()}"</span>)
<span class="cf">when</span>(intent.action) {
Intent.ACTION_BATTERY_LOW -> {
Toast.makeText(context, <span class="st">"Battery is low!"</span>, Toast.LENGTH_SHORT).show();
}
}
}</code></pre></div>
<ul>
<li>While we can use Android Studio to produce this; we’re going to make it by hand to see all the steps.</li>
</ul>
<p>But in order to <strong>register</strong> our receiver (so that Intents go past its desk), we also need to specify it in the <code>Manifest</code>. We do this by including a <code><receiver></code> element inside our <code><application></code>. Note that this is <em>not</em> an Activity, but a separate component! We can put an <code><intent-filter></code> inside of this to filter for broadcasts we care about.</p>
<div class="sourceCode"><pre class="sourceCode xml"><code class="sourceCode xml"><span class="kw"><receiver</span><span class="ot"> android:name=</span><span class="st">".PowerReceiver"</span><span class="kw">></span>
<span class="kw"><intent-filter></span>
<span class="kw"><action</span><span class="ot"> android:name=</span><span class="st">"android.intent.action.ACTION_POWER_CONNECTED"</span> <span class="kw">/></span>
<span class="kw"><action</span><span class="ot"> android:name=</span><span class="st">"android.intent.action.ACTION_POWER_DISCONNECTED"</span> <span class="kw">/></span>
<span class="kw"><action</span><span class="ot"> android:name=</span><span class="st">"android.intent.action.BATTERY_CHANGED"</span> <span class="kw">/></span>
<span class="kw"><action</span><span class="ot"> android:name=</span><span class="st">"android.intent.action.BATTERY_OKAY"</span> <span class="kw">/></span>
<span class="co"><!-- no category because not for an activity! --></span>
<span class="kw"></intent-filter></span>
<span class="kw"></receiver></span></code></pre></div>
<p class="alert alert-warning">
As of Oreo, registering for <em>implicit</em> broadcasts in the Manifest is <a href="https://developer.android.com/about/versions/oreo/background#broadcasts">not allowed</a> and will not be received correctly, with a <a href="https://developer.android.com/guide/components/broadcast-exceptions">few exceptions</a>. Instead, you would need to register receivers in code (described below). Note that setting the <code>targetSdk</code> to less than 25 is a temporary workaround.
</p>
<p>We can test these power events easily using the emulator. In the “extra options” button (the three dots at the bottom) in the emulator’s toolbar, we can get to the <code>Battery</code> tab where we can effectively change the battery status of the device (which our app can respond to!). Remember to “disconnect” from the AC Charger first!</p>
<!-- - Note that there is a `Phone` tab where you can send Text Messages to the emulator... you'll need this for your homework this week. -->
<p>We can also <em>register</em> these receivers in code (rather than in the manifest). This is good for if we only want to temporarily listen for some kind of events, or if we want to determine the <code>intent-filter</code> on the fly:</p>
<div class="sourceCode"><pre class="sourceCode java"><code class="sourceCode java"><span class="co">//java</span>
IntentFilter batteryFilter = <span class="kw">new</span> <span class="fu">IntentFilter</span>();
batteryFilter.<span class="fu">addAction</span>(Intent.<span class="fu">ACTION_BATTERY_LOW</span>);
batteryFilter.<span class="fu">addAction</span>(Intent.<span class="fu">ACTION_BATTERY_OKAY</span>);
batteryFilter.<span class="fu">addAction</span>(Intent.<span class="fu">ACTION_POWER_CONNECTED</span>);
batteryFilter.<span class="fu">addAction</span>(Intent.<span class="fu">ACTION_POWER_DISCONNECTED</span>);
<span class="kw">this</span>.<span class="fu">registerReceiver</span>(<span class="kw">new</span> <span class="fu">PowerReceiver</span>(), batteryFilter);</code></pre></div>
<div class="sourceCode"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><span class="co">//kotlin</span>
<span class="kw">val</span> <span class="va">batteryFilter</span> = IntentFilter()
batteryFilter.addAction(Intent.ACTION_BATTERY_LOW)
batteryFilter.addAction(Intent.ACTION_BATTERY_OKAY)
batteryFilter.addAction(Intent.ACTION_POWER_CONNECTED)
batteryFilter.addAction(Intent.ACTION_POWER_DISCONNECTED)
<span class="kw">this</span>.registerReceiver(PowerReceiver(), batteryFilter)</code></pre></div>
<ul>
<li>We’re dynamically declaring an <code>intent-filter</code> as well! This can be used not just for <code>BroadcastReceivers</code>, but <code>Activities</code> too, if you dynamically want to change if an Activity can receive an Intent (i.e., sometimes I can make phone calls, but sometimes I can’t).</li>
</ul>
</div>
<div id="menus" class="section level2">
<h2><span class="header-section-number">7.6</span> Menus</h2>
<p>Intents let us perform all kinds of communications and actions. But to manage all these options, it would help to introduce some more user interface components—and so in this section we’ll talk about <a href="https://developer.android.com/guide/topics/ui/menus.html"><strong><em>Menus</em></strong></a>.</p>
<p>Menus are primarily accessed through the <a href="https://developer.android.com/training/appbar/index.html"><strong>App Bar</strong></a> a.k.a. the <strong>Action Bar</strong>. This acts as the sort of “header” for your app, providing a dedicated space for navigation and interaction (e.g., through menus).</p>
<ul>
<li>The <a href="https://developer.android.com/reference/android/support/v7/app/ActionBar.html"><code>ActionBar</code></a><a href="#fn24" class="footnoteRef" id="fnref24"><sup>24</sup></a> is a specific type of <a href="https://developer.android.com/reference/android/support/v7/widget/Toolbar.html"><code>Toolbar</code></a> that is most frequently used as the App Bar, offering a particular “look and feel” common to Android applications. For this reason “App Bar” and “Action Bar” are often use interchangeably. However, it is possible to include Toolbars (and by extension, menus) wherever you want in a layout. See <a href="http://developer.android.com/training/appbar/setting-up.html">Setting up the App Bar</a> for details.</li>
</ul>
<p>The main use for the Action Bar is a place to hold <a href="https://developer.android.com/guide/topics/ui/menus.html"><strong><em>Menus</em></strong></a>. A Menu (specifically, an <a href="https://developer.android.com/guide/topics/ui/menus.html#options-menu"><strong>options menu</strong></a>) is a set of items (think: buttons) that appear in the Action Bar. Menus can be specified both in the <code>Activity</code> and in a <code>Fragment</code>; if declared in both places, they are combined into a single menu in the Action Bar. This allows you to easily make “context-specific” options menus that are only available for an appropriate Fragment, while keeping Fragments modular and self-contained.</p>
<ul>
<li><p>To give a Fragment a menu, call <code>setHasOptionsMenu(true)</code> in the Fragment’s <code>onCreate()</code> method.</p></li>
<li><p><em>Fun fact:</em> before API 11, options menus appeared as buttons at the bottom of the screen!</p></li>
</ul>
<p>Menus, like all other user-facing elements, are defined as XML resources, specifically of type <strong><code>menu</code></strong>. You can create a new menu resource through Android studio using <code>File > New > Android resource file</code> and then choosing the <code>Menu</code> Resource type. This will create an XML file with a main <a href="https://developer.android.com/reference/android/view/Menu.html"><code><menu></code></a> element.</p>
<p>Options can be added to the menu by specifying child XML elements, particularly <a href="https://developer.android.com/reference/android/view/MenuItem.html"><code><item></code></a> elements. Common <code><item></code> attributes include:</p>
<ul>
<li><strong><code>android:id</code></strong>: a unique id used to refer to the specific option in the Java code</li>
<li><strong><code>android:title</code></strong> (<strong>required</strong> attribute): the text to display for the option. As user-facing text, the content should ideally be defined as an XML String resource.</li>
<li><strong><code>app:showAsAction</code></strong>: whether or not the option should be listed in the Action Bar, or collapsed under a “three-dots” button. Note when working with the <code>appcompat</code> library, this option uses the <code>app</code> namespace (instead of <code>android</code>); you will need to include this namespace in the <code><menu></code> with the attribute <code>xmlns:app="http://schemas.android.com/apk/res-auto"</code>.</li>
<li><p><strong><code>android:icon</code></strong>: an image to use when showing the option as a button on the menu.</p>
<p class="alert alert-info">
You can use one of the many icons built into the Android, referenced as <code>"@android:drawable/ic_*"</code>. <a href="http://androiddrawables.com/">Android Drawables</a><a href="#fn25" class="footnoteRef" id="fnref25"><sup>25</sup></a> includes the full list, though not all drawables are publicly available through Android Studio.
</p></li>
<li><p><strong><code>android:orderInCategory</code></strong>: used to order the item in the menu (or in a group). This acts as a “priority” (default 0; low comes first). Such prioritizing can be useful if you want to add suggestions about whether Fragment options should come before or after the Activity options.</p></li>
</ul>
<p>See the <a href="https://developer.android.com/guide/topics/resources/menu-resource.html">Menu resources guide</a><a href="#fn26" class="footnoteRef" id="fnref26"><sup>26</sup></a> for the full list of options!</p>
<p>It is possible to include <strong>one level</strong> of sub-menus (a <code><menu></code> element inside an <code><item></code> element). Menu items can also be grouped together by placing them inside of a <code><group></code> element. All items in a group will be shown or hidden together, and can be further ordered within that group. Grouped icons can also be made <a href="https://developer.android.com/guide/topics/ui/menus.html#checkable">checkable</a>.</p>
<p>In order to show the menu in the running application, we need to tell the Action Bar which menu resource it should use (there may be a lot of resources). To do this, we override the <code>onCreateOptionsMenu()</code> callback in the Activity or Fragment, and then use the component’s <code>MenuInflater</code> object to expand the menu:</p>
<div class="sourceCode"><pre class="sourceCode java"><code class="sourceCode java"><span class="co">//java</span>
<span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">onCreateOptionsMenu</span>(<span class="bu">Menu</span> menu) {
MenuInflater inflater = <span class="fu">getMenuInflater</span>();
inflater.<span class="fu">inflate</span>(R.<span class="fu">menu</span>.<span class="fu">main_menu</span>, menu); <span class="co">//inflate into this menu</span>
<span class="kw">return</span> <span class="kw">true</span>;
}</code></pre></div>
<div class="sourceCode"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><span class="co">//kotlin</span>
<span class="kw">override</span> <span class="kw">fun</span> <span class="fu">onCreateOptionsMenu</span>(<span class="va">menu</span>: <span class="dt">Menu</span>): <span class="dt">Boolean</span> {
<span class="kw">val</span> <span class="va">inflater</span> = menuInflater
inflater.inflate(R.menu.main_menu, menu) <span class="co">//inflate into this menu</span>
<span class="kw">return</span> <span class="kw">true</span>
}</code></pre></div>
<ul>
<li>This procedure is similar in concept to how a Fragment’s <code>onViewCreated()</code> method would inflate the Fragment into the Activity. In this case, the Menu is being inflated into the Action Bar.</li>
</ul>
<p>We can respond to the menu items being selected by overriding the <code>onOptionsItemSelected()</code> callback. By convention, in Java we use a <code>switch</code> on the <code>item.getItemId()</code> to determine what item was selected, and then act accordingly. In Kotlin, use a <code>when</code> expression that will be returned.</p>
<div class="sourceCode"><pre class="sourceCode java"><code class="sourceCode java"><span class="co">//java</span>
<span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">onOptionsItemSelected</span>(<span class="bu">MenuItem</span> item) {
<span class="kw">switch</span>(item.<span class="fu">getItemId</span>()){
<span class="kw">case</span> R.<span class="fu">id</span>.<span class="fu">menu_item1</span> :
<span class="co">//do thing;</span>
<span class="kw">return</span> <span class="kw">true</span>;
<span class="kw">default</span>:
<span class="kw">return</span> <span class="kw">super</span>.<span class="fu">onOptionsItemSelected</span>(item);
}
}</code></pre></div>
<div class="sourceCode"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><span class="co">//kotlin</span>
<span class="kw">override</span> <span class="kw">fun</span> <span class="fu">onOptionsItemSelected</span>(<span class="va">item</span>: <span class="dt">MenuItem</span>): <span class="dt">Boolean</span> {
<span class="kw">return</span> <span class="cf">when</span> (item.itemId) {
R.id.menu_item1 -> {
<span class="co">//do thing</span>
<span class="kw">true</span>
}
<span class="cf">else</span> -> <span class="kw">super</span>.onOptionsItemSelected(item)
}
}</code></pre></div>
<ul>
<li><p>On <code>default</code> (if the item selected isn’t handled by any cases), we pass the callback up to <code>super</code> for “higher-level” components to check. For example, if a the menu option isn’t handled by the Fragment (because the Fragment didn’t add it), the event can be passed up through the Framework for eventually handling by the Activity (who did add it).</p></li>
<li><p>This method should return <code>true</code> if the selection even has been handled (and thus should not be considered by anyone else). Return <code>false</code> if you want other components (e.g., other Fragments) to be able to respond to this option as well.</p></li>
</ul>
<p>There are many other menu items that can be placed on Action Bar as well. We can also add <a href="https://developer.android.com/training/appbar/action-views.html">Action Views</a> that provide more complex interactions than just clicking buttons (for example, including a search bar). An <a href="https://developer.android.com/training/appbar/action-views.html#action-provider">Action Provider</a> (like <a href="https://developer.android.com/training/sharing/shareaction.html"><code>ShareActionProvider</code></a>) is an action with its own customized layout, expanding into a separate View when clicked.</p>
<div id="action-views" class="section level3 unnumbered">
<h3>Action Views</h3>
<p>In addition to these simple buttons, we can also include more complex expandable widgets called <a href="https://developer.android.com/training/appbar/action-views.html">Action Views</a>. The most common of these is a <a href="https://developer.android.com/reference/android/support/v7/widget/SearchView.html">SearchView</a>, which puts a “search field” in the App Bar!</p>
<p>However, as a slightly simpler demo, we’ll set up a <a href="https://developer.android.com/training/sharing/shareaction.html"><code>ShareActionProvider</code></a>, which automatically provides a drop-down menu item with a complete list of apps that we can share our data with (e.g., the “quick share with these social media sites” button)y.</p>
<ul>
<li>For reference, I recommend looking at the <a href="http://developer.android.com/reference/android/support/v7/widget/ShareActionProvider.html">class documentation</a> for how to set this up (it’s much clearer than the training docs).</li>
</ul>
<p>We’ll start by adding another item to our menu’s XML. This will look like other items, except it will have an extra field <code>app:actionProviderClass</code> indicating that this item is an Action Provider (a widget that provides some actions)</p>
<div class="sourceCode"><pre class="sourceCode xml"><code class="sourceCode xml"><span class="kw"><item</span>
<span class="ot"> android:id=</span><span class="st">"@+id/menu_item_share"</span>
<span class="ot"> android:title=</span><span class="st">"Share"</span>
<span class="ot"> app:showAsAction=</span><span class="st">"ifRoom"</span>
<span class="ot"> app:actionProviderClass=</span><span class="st">"android.support.v7.widget.ShareActionProvider"</span>
<span class="kw">/></span></code></pre></div>
<p>We’ll then add the item to our menu in <code>onCreateOptionsMenu()</code></p>
<div class="sourceCode"><pre class="sourceCode java"><code class="sourceCode java"><span class="co">//java</span>
<span class="bu">MenuItem</span> item = menu.<span class="fu">findItem</span>(R.<span class="fu">id</span>.<span class="fu">menu_item_share</span>);
ShareActionProvider shareProvider = (ShareActionProvider)MenuItemCompat.<span class="fu">getActionProvider</span>(item);
Intent intent = <span class="kw">new</span> <span class="fu">Intent</span>(Intent.<span class="fu">ACTION_DIAL</span>);
intent.<span class="fu">setData</span>(Uri.<span class="fu">parse</span>(<span class="st">"tel:206-685-1622"</span>));
shareProvider.<span class="fu">setShareIntent</span>(intent);</code></pre></div>
<div class="sourceCode"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><span class="co">//kotlin</span>
<span class="kw">val</span> <span class="va">item</span> = menu.findItem(R.id.menu_item_share)
<span class="kw">val</span> <span class="va">shareProvider</span> = MenuItemCompat.getActionProvider(item) <span class="kw">as</span> ShareActionProvider
<span class="kw">val</span> <span class="va">intent</span> = Intent(Intent.ACTION_DIAL)
intent.<span class="kw">data</span> = Uri.parse(<span class="st">"tel:206-685-1622"</span>)
shareProvider.setShareIntent(intent)</code></pre></div>
<ul>
<li><p>We get access to the item using <code>findItem()</code> (similar to <code>findViewById()</code>), and then cast it to a <code>ShareActonProvider</code> (make sure you’re using the support version!)</p></li>
<li><p>We can then specify an <em>Implicit Intent</em> that we want that “Share Button” to be able to perform. This would commonly use the <code>ACTION_SEND</code> action (like for sharing a picture or text), but we’ll use the <code>DIAL</code> action because we have a couple of dialers but don’t actually have many <code>SEND</code> responders on the emulator.</p></li>
</ul>
<p>The Menu item will then list a dropdown with all of the different Activities that <code>resolve</code> to handling that implicit intent! And we’ve now deeply combined Intents and Menus!</p>
</div>
<div id="context-menus" class="section level3 unnumbered">
<h3>Context Menus</h3>
<p>In addition to options menus available in the Action Bar, we can also specify <a href="https://developer.android.com/guide/topics/ui/menus.html#context-menu">contextual menus</a> that pop up when the user long-presses on an element. This works similarly to using an options menu, but with a different set off callbacks:</p>
<ul>
<li><p>When setting up the the View layout (e.g., in an Activity’s <code>onCreate()</code>), we specify that an element has a context menu using the <code>registerForContextMenu()</code> method, passing it the <code>View</code> we want to be able to create the menu for.</p></li>
<li><p>Specify the context menu to use through the <code>onCreateContextMenu()</code> callback. This works exactly like setting up an options menu.</p>
<ul>
<li>In fact, a context menu can even use <em>the same menu</em> as an options menu! This reuse is one of the advantages of defining the user interface as XML.</li>
</ul></li>
<li><p>And mirroring the options menu, respond to context menu items being selected with the <code>onContextItemSelected()</code> callback.</p></li>
</ul>
<p>This section has provided a very brief introduction to menus, but there are many more complex interactions that they support. I <em>highly</em> recommend that you read through <a href="https://developer.android.com/guide/topics/ui/menus.html">the guide</a> in order to learn what features may be available.</p>
<p class="alert alert-info">
If you ever are using an app and wonder “how did they add this interface feature?”, look it up! There is almost always a documented procedure and example for providing that kind of component.
</p>
</div>
</div>
<div id="an-intent-example-sms" class="section level2">
<h2><span class="header-section-number">7.7</span> An Intent Example: SMS</h2>
<p class="alert alert-info">
An optional extra example, for the curious.
</p>
<p>One specific use of Intents is when working with text messages (SMS, Short Messaging Service, the most popular form of data communication in the world). In particular, Intents are used to send and receive SMS messages (you can get a list of messages already received using a <code>ContentProvided</code>, described in a later lecture).</p>
<ul>
<li><em>Important note:</em> the SMS APIs changed <em>drastically</em> in KitKat (API 19). So we’re going to make sure that is our minimum so we can get all the helpful methods and support newer stuff (check gradle to confirm!).</li>
</ul>
<p>The main thing to note about sending SMS is that as of KitKat, each system has a <em>default</em> messaging client—which is the only app that can actually send messages. Luckily, the API lets you get access to that messaging client’s services in order to send a message <em>through</em> it:</p>
<div class="sourceCode"><pre class="sourceCode java"><code class="sourceCode java">SmsManager smsManager = SmsManager.<span class="fu">getDefault</span>();
smsManager.<span class="fu">sendTextMessage</span>(<span class="st">"5554"</span>, <span class="kw">null</span>, <span class="st">"This is a test message!"</span>, <span class="kw">null</span>, <span class="kw">null</span>);
<span class="co">// target, message</span></code></pre></div>
<ul>
<li><code>5554</code> is the default “phone number” of the emulator (the port it is running on).</li>
</ul>
<p>We will also need permission: <code><uses-permission android:name="android.permission.SEND_SMS" /></code> (in the Manifest). Note that you’ll need to target SDK 22 or lower for this to work without extra details; see the lecture on Permissions for more information.</p>
<p>You can see that this works by looking at the inbox in the Messages app… but there is another way as well! If you look at <a href="http://developer.android.com/reference/android/telephony/SmsManager.html#sendTextMessage(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent)">the documentation for this method</a><a href="#fn27" class="footnoteRef" id="fnref27"><sup>27</sup></a>, you can see that the last two parameters are for <a href="http://developer.android.com/reference/android/app/PendingIntent.html"><code>PendingIntents</code></a>: one for when messages are sent and one for when messages are delivered.</p>
<ul>
<li><p>What’s a <code>PendingIntent</code>? The details are not <em>super</em> readable… It’s basically a wrapper around an <code>Intent</code> that we give to <strong>another</strong> class. Then when that class receives our <code>PendingIntent</code> and reacts to it, it can run the <code>Intent</code> (command) we sent it with as if that <code>Activity</code> were us (whew).</p>
<ul>
<li>This is like when you ask a professor for a letter of recommendation, and you give them the stamped envelope (which you should always do!). When they get the packet, then can then send their letter using <em>your</em> envelop and stamp!</li>
<li>Alternatively: “I am mailing you my car keys, when you get them you can come pick me up”.</li>
</ul></li>
<li><p>So the idea is we specify what <code>Intent</code> should be delivered when the message is finished being sent (that <code>Intent</code> becomes “pending”). Effectively, this let’s us send Intents in response to some other kind of event.</p></li>
</ul>
<p>Let’s go ahead and set one up:</p>
<div class="sourceCode"><pre class="sourceCode java"><code class="sourceCode java"><span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> <span class="bu">String</span> ACTION_SMS_STATUS = <span class="st">"edu.uw.intentdemo.ACTION_SMS_STATUS"</span>;
<span class="co">//...</span>
Intent intent = <span class="kw">new</span> <span class="fu">Intent</span>(ACTION_SMS_STATUS);
PendingIntent pendingIntent = PendingIntent.<span class="fu">getBroadcast</span>(MainActivity.<span class="fu">this</span>, <span class="dv">0</span>, intent, <span class="dv">0</span>);
smsManager.<span class="fu">sendTextMessage</span>(<span class="st">"5554"</span>, <span class="kw">null</span>, <span class="st">"This is a test message!"</span>, pendingIntent, <span class="kw">null</span>);</code></pre></div>
<p>We’re doing a couple of steps here:</p>
<ul>
<li>We’re defining our own custom Action. It’s just a <code>String</code>, but name-spaced to avoid conflicts</li>
<li>We then create an <strong>Implicit Intent</strong> for this action</li>
<li>And then create a <code>PendingIntent</code>. We’re using the <code>getBroadcast()</code> method to specify that the Intent should be sent via a Broadcast (c.f. <code>getActivity()</code> for <code>startActivity()</code>).
<ul>
<li>First param is the Context that should send the Intent, then a request code (e.g., for result callbacks if we wanted), then the <code>Intent</code> we want to be pending, and finally any extra flags (none for now).</li>
</ul></li>
</ul>
<p>We can then have our <code>BroadcastReceiver</code> respond to this <code>Intent</code> just like any other one!</p>
<div class="sourceCode"><pre class="sourceCode java"><code class="sourceCode java"><span class="kw">if</span>(intent.<span class="fu">getAction</span>() == MainActivity.<span class="fu">ACTION_SMS_STATUS</span>) {
<span class="kw">if</span> (<span class="fu">getResultCode</span>() == Activity.<span class="fu">RESULT_OK</span>) {
Toast.<span class="fu">makeText</span>(context, <span class="st">"Message sent!"</span>, Toast.<span class="fu">LENGTH_SHORT</span>).<span class="fu">show</span>();
}
<span class="kw">else</span> {
Toast.<span class="fu">makeText</span>(context, <span class="st">"Error sending message"</span>, Toast.<span class="fu">LENGTH_SHORT</span>).<span class="fu">show</span>();
}
}</code></pre></div>
<ul>
<li><strong>Don’t forget</strong> to add our custom intent to the <code><intent-filter></code>!</li>
</ul>
<p>We’ll see more with <code>PendingIntents</code> in the next chapter when we talk about notifications.</p>
</div>
</div>
<div class="footnotes">
<hr />
<ol start="21">
<li id="fn21"><p><a href="https://developer.android.com/reference/android/content/Intent.html" class="uri">https://developer.android.com/reference/android/content/Intent.html</a><a href="intents.html#fnref21">↩</a></p></li>
<li id="fn22"><p><a href="https://developer.android.com/guide/components/intents-common.html" class="uri">https://developer.android.com/guide/components/intents-common.html</a><a href="intents.html#fnref22">↩</a></p></li>
<li id="fn23"><p><a href="http://developer.android.com/training/camera/photobasics.html#TaskPath" class="uri">http://developer.android.com/training/camera/photobasics.html#TaskPath</a><a href="intents.html#fnref23">↩</a></p></li>
<li id="fn24"><p><a href="http://developer.android.com/reference/android/support/v7/app/ActionBar.html" class="uri">http://developer.android.com/reference/android/support/v7/app/ActionBar.html</a><a href="intents.html#fnref24">↩</a></p></li>
<li id="fn25"><p><a href="http://androiddrawables.com/" class="uri">http://androiddrawables.com/</a><a href="intents.html#fnref25">↩</a></p></li>
<li id="fn26"><p><a href="https://developer.android.com/guide/topics/resources/menu-resource.html" class="uri">https://developer.android.com/guide/topics/resources/menu-resource.html</a><a href="intents.html#fnref26">↩</a></p></li>
<li id="fn27"><p><a href="https://developer.android.com/reference/android/telephony/SmsManager.html" class="uri">https://developer.android.com/reference/android/telephony/SmsManager.html</a><a href="intents.html#fnref27">↩</a></p></li>
</ol>
</div>
</section>
</div>
</div>
</div>
<a href="fragments.html" class="navigation navigation-prev " aria-label="Previous page"><i class="fa fa-angle-left"></i></a>
<a href="notifications-settings.html" class="navigation navigation-next " aria-label="Next page"><i class="fa fa-angle-right"></i></a>
</div>
</div>
<script src="libs/gitbook-2.6.7/js/app.min.js"></script>
<script src="libs/gitbook-2.6.7/js/lunr.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-search.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-sharing.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-fontsettings.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-bookdown.js"></script>
<script src="libs/gitbook-2.6.7/js/jquery.highlight.js"></script>
<script>
gitbook.require(["gitbook"], function(gitbook) {
gitbook.start({
"sharing": {
"github": true,
"facebook": false,
"twitter": false,
"google": false,
"weibo": false,
"instapper": false,
"vk": false,
"all": ["github", "facebook", "twitter", "google"]
},
"fontsettings": {
"theme": "white",
"family": "sans",
"size": 2
},
"edit": {
"link": "https://github.com/info448/book/edit/master/intents.Rmd",
"text": "Edit"
},
"download": ["android-development.pdf", "android-development.epub"],
"toc": {
"collapse": "section",
"scroll_highlight": true
}
});
});
</script>
<!-- dynamically load mathjax for compatibility with self-contained -->
<script>
(function () {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://cdn.bootcss.com/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML";
if (location.protocol !== "file:" && /^https?:/.test(script.src))
script.src = script.src.replace(/^https?:/, '');
document.getElementsByTagName("head")[0].appendChild(script);
})();
</script>
</body>
</html>