Parcourir la source

Merge branch 'devel'

yattoz il y a 4 ans
Parent
révision
6bbc958dce
49 fichiers modifiés avec 190 ajouts et 771 suppressions
  1. 3 0
      .gitmodules
  2. 22 0
      .idea/gradle.xml
  3. 1 0
      .idea/vcs.xml
  4. 1 0
      ExoPlayer
  5. 21 674
      LICENSE
  6. 9 3
      app/build.gradle
  7. BIN
      app/src/main/assets/the_stream_is_down.mp3
  8. BIN
      app/src/main/ic_launcher-web.png
  9. 2 2
      app/src/main/java/fr/forum_thalie/tsumugi/BaseNotification.kt
  10. 6 3
      app/src/main/java/fr/forum_thalie/tsumugi/RadioService.kt
  11. 2 1
      app/src/main/java/fr/forum_thalie/tsumugi/Values.kt
  12. 21 18
      app/src/main/java/fr/forum_thalie/tsumugi/alarm/RadioAlarm.kt
  13. 24 16
      app/src/main/java/fr/forum_thalie/tsumugi/alarm/RadioSleeper.kt
  14. 27 15
      app/src/main/java/fr/forum_thalie/tsumugi/ui/news/NewsAdapter.kt
  15. 2 2
      app/src/main/java/fr/forum_thalie/tsumugi/ui/news/NewsFragment.kt
  16. 6 7
      app/src/main/java/fr/forum_thalie/tsumugi/ui/news/NewsViewModel.kt
  17. 11 0
      app/src/main/res/drawable-anydpi/ic_settings.xml
  18. BIN
      app/src/main/res/drawable-hdpi/ic_notif_lollipop_icon.png
  19. BIN
      app/src/main/res/drawable-hdpi/ic_settings.png
  20. BIN
      app/src/main/res/drawable-mdpi/ic_notif_lollipop_icon.png
  21. BIN
      app/src/main/res/drawable-mdpi/ic_settings.png
  22. BIN
      app/src/main/res/drawable-xhdpi/ic_notif_lollipop_icon.png
  23. BIN
      app/src/main/res/drawable-xhdpi/ic_settings.png
  24. BIN
      app/src/main/res/drawable-xxhdpi/ic_notif_lollipop_icon.png
  25. BIN
      app/src/main/res/drawable-xxhdpi/ic_settings.png
  26. BIN
      app/src/main/res/drawable-xxxhdpi/ic_notif_lollipop_icon.png
  27. 3 3
      app/src/main/res/layout/fragment_nowplaying.xml
  28. 2 1
      app/src/main/res/menu/toolbar_menu.xml
  29. 1 1
      app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
  30. 1 1
      app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
  31. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher.png
  32. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
  33. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher_round.png
  34. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher.png
  35. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
  36. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher_round.png
  37. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher.png
  38. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
  39. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
  40. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  41. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
  42. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
  43. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  44. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
  45. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
  46. 2 16
      app/src/main/res/values-fr/strings.xml
  47. 6 0
      app/src/main/res/values-v21/strings.xml
  48. 13 8
      app/src/main/res/values/strings.xml
  49. 4 0
      settings.gradle

+ 3 - 0
.gitmodules Voir le fichier

@@ -0,0 +1,3 @@
1
+[submodule "ExoPlayer"]
2
+	path = ExoPlayer
3
+	url = https://github.com/google/ExoPlayer/

+ 22 - 0
.idea/gradle.xml Voir le fichier

@@ -8,6 +8,28 @@
8 8
         <option name="modules">
9 9
           <set>
10 10
             <option value="$PROJECT_DIR$" />
11
+            <option value="$PROJECT_DIR$/ExoPlayer/extensions/av1" />
12
+            <option value="$PROJECT_DIR$/ExoPlayer/extensions/cast" />
13
+            <option value="$PROJECT_DIR$/ExoPlayer/extensions/cronet" />
14
+            <option value="$PROJECT_DIR$/ExoPlayer/extensions/ffmpeg" />
15
+            <option value="$PROJECT_DIR$/ExoPlayer/extensions/flac" />
16
+            <option value="$PROJECT_DIR$/ExoPlayer/extensions/gvr" />
17
+            <option value="$PROJECT_DIR$/ExoPlayer/extensions/ima" />
18
+            <option value="$PROJECT_DIR$/ExoPlayer/extensions/jobdispatcher" />
19
+            <option value="$PROJECT_DIR$/ExoPlayer/extensions/leanback" />
20
+            <option value="$PROJECT_DIR$/ExoPlayer/extensions/mediasession" />
21
+            <option value="$PROJECT_DIR$/ExoPlayer/extensions/okhttp" />
22
+            <option value="$PROJECT_DIR$/ExoPlayer/extensions/opus" />
23
+            <option value="$PROJECT_DIR$/ExoPlayer/extensions/rtmp" />
24
+            <option value="$PROJECT_DIR$/ExoPlayer/extensions/vp9" />
25
+            <option value="$PROJECT_DIR$/ExoPlayer/extensions/workmanager" />
26
+            <option value="$PROJECT_DIR$/ExoPlayer/library/all" />
27
+            <option value="$PROJECT_DIR$/ExoPlayer/library/core" />
28
+            <option value="$PROJECT_DIR$/ExoPlayer/library/dash" />
29
+            <option value="$PROJECT_DIR$/ExoPlayer/library/hls" />
30
+            <option value="$PROJECT_DIR$/ExoPlayer/library/smoothstreaming" />
31
+            <option value="$PROJECT_DIR$/ExoPlayer/library/ui" />
32
+            <option value="$PROJECT_DIR$/ExoPlayer/testutils" />
11 33
             <option value="$PROJECT_DIR$/app" />
12 34
           </set>
13 35
         </option>

+ 1 - 0
.idea/vcs.xml Voir le fichier

@@ -2,5 +2,6 @@
2 2
 <project version="4">
3 3
   <component name="VcsDirectoryMappings">
4 4
     <mapping directory="" vcs="Git" />
5
+    <mapping directory="$PROJECT_DIR$/ExoPlayer" vcs="Git" />
5 6
   </component>
6 7
 </project>

+ 1 - 0
ExoPlayer

@@ -0,0 +1 @@
1
+Subproject commit 24a19264dbf35e326bbd7bb36c232eb180e1e26d

+ 21 - 674
LICENSE Voir le fichier

@@ -1,674 +1,21 @@
1
-                    GNU GENERAL PUBLIC LICENSE
2
-                       Version 3, 29 June 2007
3
-
4
- Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5
- Everyone is permitted to copy and distribute verbatim copies
6
- of this license document, but changing it is not allowed.
7
-
8
-                            Preamble
9
-
10
-  The GNU General Public License is a free, copyleft license for
11
-software and other kinds of works.
12
-
13
-  The licenses for most software and other practical works are designed
14
-to take away your freedom to share and change the works.  By contrast,
15
-the GNU General Public License is intended to guarantee your freedom to
16
-share and change all versions of a program--to make sure it remains free
17
-software for all its users.  We, the Free Software Foundation, use the
18
-GNU General Public License for most of our software; it applies also to
19
-any other work released this way by its authors.  You can apply it to
20
-your programs, too.
21
-
22
-  When we speak of free software, we are referring to freedom, not
23
-price.  Our General Public Licenses are designed to make sure that you
24
-have the freedom to distribute copies of free software (and charge for
25
-them if you wish), that you receive source code or can get it if you
26
-want it, that you can change the software or use pieces of it in new
27
-free programs, and that you know you can do these things.
28
-
29
-  To protect your rights, we need to prevent others from denying you
30
-these rights or asking you to surrender the rights.  Therefore, you have
31
-certain responsibilities if you distribute copies of the software, or if
32
-you modify it: responsibilities to respect the freedom of others.
33
-
34
-  For example, if you distribute copies of such a program, whether
35
-gratis or for a fee, you must pass on to the recipients the same
36
-freedoms that you received.  You must make sure that they, too, receive
37
-or can get the source code.  And you must show them these terms so they
38
-know their rights.
39
-
40
-  Developers that use the GNU GPL protect your rights with two steps:
41
-(1) assert copyright on the software, and (2) offer you this License
42
-giving you legal permission to copy, distribute and/or modify it.
43
-
44
-  For the developers' and authors' protection, the GPL clearly explains
45
-that there is no warranty for this free software.  For both users' and
46
-authors' sake, the GPL requires that modified versions be marked as
47
-changed, so that their problems will not be attributed erroneously to
48
-authors of previous versions.
49
-
50
-  Some devices are designed to deny users access to install or run
51
-modified versions of the software inside them, although the manufacturer
52
-can do so.  This is fundamentally incompatible with the aim of
53
-protecting users' freedom to change the software.  The systematic
54
-pattern of such abuse occurs in the area of products for individuals to
55
-use, which is precisely where it is most unacceptable.  Therefore, we
56
-have designed this version of the GPL to prohibit the practice for those
57
-products.  If such problems arise substantially in other domains, we
58
-stand ready to extend this provision to those domains in future versions
59
-of the GPL, as needed to protect the freedom of users.
60
-
61
-  Finally, every program is threatened constantly by software patents.
62
-States should not allow patents to restrict development and use of
63
-software on general-purpose computers, but in those that do, we wish to
64
-avoid the special danger that patents applied to a free program could
65
-make it effectively proprietary.  To prevent this, the GPL assures that
66
-patents cannot be used to render the program non-free.
67
-
68
-  The precise terms and conditions for copying, distribution and
69
-modification follow.
70
-
71
-                       TERMS AND CONDITIONS
72
-
73
-  0. Definitions.
74
-
75
-  "This License" refers to version 3 of the GNU General Public License.
76
-
77
-  "Copyright" also means copyright-like laws that apply to other kinds of
78
-works, such as semiconductor masks.
79
-
80
-  "The Program" refers to any copyrightable work licensed under this
81
-License.  Each licensee is addressed as "you".  "Licensees" and
82
-"recipients" may be individuals or organizations.
83
-
84
-  To "modify" a work means to copy from or adapt all or part of the work
85
-in a fashion requiring copyright permission, other than the making of an
86
-exact copy.  The resulting work is called a "modified version" of the
87
-earlier work or a work "based on" the earlier work.
88
-
89
-  A "covered work" means either the unmodified Program or a work based
90
-on the Program.
91
-
92
-  To "propagate" a work means to do anything with it that, without
93
-permission, would make you directly or secondarily liable for
94
-infringement under applicable copyright law, except executing it on a
95
-computer or modifying a private copy.  Propagation includes copying,
96
-distribution (with or without modification), making available to the
97
-public, and in some countries other activities as well.
98
-
99
-  To "convey" a work means any kind of propagation that enables other
100
-parties to make or receive copies.  Mere interaction with a user through
101
-a computer network, with no transfer of a copy, is not conveying.
102
-
103
-  An interactive user interface displays "Appropriate Legal Notices"
104
-to the extent that it includes a convenient and prominently visible
105
-feature that (1) displays an appropriate copyright notice, and (2)
106
-tells the user that there is no warranty for the work (except to the
107
-extent that warranties are provided), that licensees may convey the
108
-work under this License, and how to view a copy of this License.  If
109
-the interface presents a list of user commands or options, such as a
110
-menu, a prominent item in the list meets this criterion.
111
-
112
-  1. Source Code.
113
-
114
-  The "source code" for a work means the preferred form of the work
115
-for making modifications to it.  "Object code" means any non-source
116
-form of a work.
117
-
118
-  A "Standard Interface" means an interface that either is an official
119
-standard defined by a recognized standards body, or, in the case of
120
-interfaces specified for a particular programming language, one that
121
-is widely used among developers working in that language.
122
-
123
-  The "System Libraries" of an executable work include anything, other
124
-than the work as a whole, that (a) is included in the normal form of
125
-packaging a Major Component, but which is not part of that Major
126
-Component, and (b) serves only to enable use of the work with that
127
-Major Component, or to implement a Standard Interface for which an
128
-implementation is available to the public in source code form.  A
129
-"Major Component", in this context, means a major essential component
130
-(kernel, window system, and so on) of the specific operating system
131
-(if any) on which the executable work runs, or a compiler used to
132
-produce the work, or an object code interpreter used to run it.
133
-
134
-  The "Corresponding Source" for a work in object code form means all
135
-the source code needed to generate, install, and (for an executable
136
-work) run the object code and to modify the work, including scripts to
137
-control those activities.  However, it does not include the work's
138
-System Libraries, or general-purpose tools or generally available free
139
-programs which are used unmodified in performing those activities but
140
-which are not part of the work.  For example, Corresponding Source
141
-includes interface definition files associated with source files for
142
-the work, and the source code for shared libraries and dynamically
143
-linked subprograms that the work is specifically designed to require,
144
-such as by intimate data communication or control flow between those
145
-subprograms and other parts of the work.
146
-
147
-  The Corresponding Source need not include anything that users
148
-can regenerate automatically from other parts of the Corresponding
149
-Source.
150
-
151
-  The Corresponding Source for a work in source code form is that
152
-same work.
153
-
154
-  2. Basic Permissions.
155
-
156
-  All rights granted under this License are granted for the term of
157
-copyright on the Program, and are irrevocable provided the stated
158
-conditions are met.  This License explicitly affirms your unlimited
159
-permission to run the unmodified Program.  The output from running a
160
-covered work is covered by this License only if the output, given its
161
-content, constitutes a covered work.  This License acknowledges your
162
-rights of fair use or other equivalent, as provided by copyright law.
163
-
164
-  You may make, run and propagate covered works that you do not
165
-convey, without conditions so long as your license otherwise remains
166
-in force.  You may convey covered works to others for the sole purpose
167
-of having them make modifications exclusively for you, or provide you
168
-with facilities for running those works, provided that you comply with
169
-the terms of this License in conveying all material for which you do
170
-not control copyright.  Those thus making or running the covered works
171
-for you must do so exclusively on your behalf, under your direction
172
-and control, on terms that prohibit them from making any copies of
173
-your copyrighted material outside their relationship with you.
174
-
175
-  Conveying under any other circumstances is permitted solely under
176
-the conditions stated below.  Sublicensing is not allowed; section 10
177
-makes it unnecessary.
178
-
179
-  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
-
181
-  No covered work shall be deemed part of an effective technological
182
-measure under any applicable law fulfilling obligations under article
183
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
184
-similar laws prohibiting or restricting circumvention of such
185
-measures.
186
-
187
-  When you convey a covered work, you waive any legal power to forbid
188
-circumvention of technological measures to the extent such circumvention
189
-is effected by exercising rights under this License with respect to
190
-the covered work, and you disclaim any intention to limit operation or
191
-modification of the work as a means of enforcing, against the work's
192
-users, your or third parties' legal rights to forbid circumvention of
193
-technological measures.
194
-
195
-  4. Conveying Verbatim Copies.
196
-
197
-  You may convey verbatim copies of the Program's source code as you
198
-receive it, in any medium, provided that you conspicuously and
199
-appropriately publish on each copy an appropriate copyright notice;
200
-keep intact all notices stating that this License and any
201
-non-permissive terms added in accord with section 7 apply to the code;
202
-keep intact all notices of the absence of any warranty; and give all
203
-recipients a copy of this License along with the Program.
204
-
205
-  You may charge any price or no price for each copy that you convey,
206
-and you may offer support or warranty protection for a fee.
207
-
208
-  5. Conveying Modified Source Versions.
209
-
210
-  You may convey a work based on the Program, or the modifications to
211
-produce it from the Program, in the form of source code under the
212
-terms of section 4, provided that you also meet all of these conditions:
213
-
214
-    a) The work must carry prominent notices stating that you modified
215
-    it, and giving a relevant date.
216
-
217
-    b) The work must carry prominent notices stating that it is
218
-    released under this License and any conditions added under section
219
-    7.  This requirement modifies the requirement in section 4 to
220
-    "keep intact all notices".
221
-
222
-    c) You must license the entire work, as a whole, under this
223
-    License to anyone who comes into possession of a copy.  This
224
-    License will therefore apply, along with any applicable section 7
225
-    additional terms, to the whole of the work, and all its parts,
226
-    regardless of how they are packaged.  This License gives no
227
-    permission to license the work in any other way, but it does not
228
-    invalidate such permission if you have separately received it.
229
-
230
-    d) If the work has interactive user interfaces, each must display
231
-    Appropriate Legal Notices; however, if the Program has interactive
232
-    interfaces that do not display Appropriate Legal Notices, your
233
-    work need not make them do so.
234
-
235
-  A compilation of a covered work with other separate and independent
236
-works, which are not by their nature extensions of the covered work,
237
-and which are not combined with it such as to form a larger program,
238
-in or on a volume of a storage or distribution medium, is called an
239
-"aggregate" if the compilation and its resulting copyright are not
240
-used to limit the access or legal rights of the compilation's users
241
-beyond what the individual works permit.  Inclusion of a covered work
242
-in an aggregate does not cause this License to apply to the other
243
-parts of the aggregate.
244
-
245
-  6. Conveying Non-Source Forms.
246
-
247
-  You may convey a covered work in object code form under the terms
248
-of sections 4 and 5, provided that you also convey the
249
-machine-readable Corresponding Source under the terms of this License,
250
-in one of these ways:
251
-
252
-    a) Convey the object code in, or embodied in, a physical product
253
-    (including a physical distribution medium), accompanied by the
254
-    Corresponding Source fixed on a durable physical medium
255
-    customarily used for software interchange.
256
-
257
-    b) Convey the object code in, or embodied in, a physical product
258
-    (including a physical distribution medium), accompanied by a
259
-    written offer, valid for at least three years and valid for as
260
-    long as you offer spare parts or customer support for that product
261
-    model, to give anyone who possesses the object code either (1) a
262
-    copy of the Corresponding Source for all the software in the
263
-    product that is covered by this License, on a durable physical
264
-    medium customarily used for software interchange, for a price no
265
-    more than your reasonable cost of physically performing this
266
-    conveying of source, or (2) access to copy the
267
-    Corresponding Source from a network server at no charge.
268
-
269
-    c) Convey individual copies of the object code with a copy of the
270
-    written offer to provide the Corresponding Source.  This
271
-    alternative is allowed only occasionally and noncommercially, and
272
-    only if you received the object code with such an offer, in accord
273
-    with subsection 6b.
274
-
275
-    d) Convey the object code by offering access from a designated
276
-    place (gratis or for a charge), and offer equivalent access to the
277
-    Corresponding Source in the same way through the same place at no
278
-    further charge.  You need not require recipients to copy the
279
-    Corresponding Source along with the object code.  If the place to
280
-    copy the object code is a network server, the Corresponding Source
281
-    may be on a different server (operated by you or a third party)
282
-    that supports equivalent copying facilities, provided you maintain
283
-    clear directions next to the object code saying where to find the
284
-    Corresponding Source.  Regardless of what server hosts the
285
-    Corresponding Source, you remain obligated to ensure that it is
286
-    available for as long as needed to satisfy these requirements.
287
-
288
-    e) Convey the object code using peer-to-peer transmission, provided
289
-    you inform other peers where the object code and Corresponding
290
-    Source of the work are being offered to the general public at no
291
-    charge under subsection 6d.
292
-
293
-  A separable portion of the object code, whose source code is excluded
294
-from the Corresponding Source as a System Library, need not be
295
-included in conveying the object code work.
296
-
297
-  A "User Product" is either (1) a "consumer product", which means any
298
-tangible personal property which is normally used for personal, family,
299
-or household purposes, or (2) anything designed or sold for incorporation
300
-into a dwelling.  In determining whether a product is a consumer product,
301
-doubtful cases shall be resolved in favor of coverage.  For a particular
302
-product received by a particular user, "normally used" refers to a
303
-typical or common use of that class of product, regardless of the status
304
-of the particular user or of the way in which the particular user
305
-actually uses, or expects or is expected to use, the product.  A product
306
-is a consumer product regardless of whether the product has substantial
307
-commercial, industrial or non-consumer uses, unless such uses represent
308
-the only significant mode of use of the product.
309
-
310
-  "Installation Information" for a User Product means any methods,
311
-procedures, authorization keys, or other information required to install
312
-and execute modified versions of a covered work in that User Product from
313
-a modified version of its Corresponding Source.  The information must
314
-suffice to ensure that the continued functioning of the modified object
315
-code is in no case prevented or interfered with solely because
316
-modification has been made.
317
-
318
-  If you convey an object code work under this section in, or with, or
319
-specifically for use in, a User Product, and the conveying occurs as
320
-part of a transaction in which the right of possession and use of the
321
-User Product is transferred to the recipient in perpetuity or for a
322
-fixed term (regardless of how the transaction is characterized), the
323
-Corresponding Source conveyed under this section must be accompanied
324
-by the Installation Information.  But this requirement does not apply
325
-if neither you nor any third party retains the ability to install
326
-modified object code on the User Product (for example, the work has
327
-been installed in ROM).
328
-
329
-  The requirement to provide Installation Information does not include a
330
-requirement to continue to provide support service, warranty, or updates
331
-for a work that has been modified or installed by the recipient, or for
332
-the User Product in which it has been modified or installed.  Access to a
333
-network may be denied when the modification itself materially and
334
-adversely affects the operation of the network or violates the rules and
335
-protocols for communication across the network.
336
-
337
-  Corresponding Source conveyed, and Installation Information provided,
338
-in accord with this section must be in a format that is publicly
339
-documented (and with an implementation available to the public in
340
-source code form), and must require no special password or key for
341
-unpacking, reading or copying.
342
-
343
-  7. Additional Terms.
344
-
345
-  "Additional permissions" are terms that supplement the terms of this
346
-License by making exceptions from one or more of its conditions.
347
-Additional permissions that are applicable to the entire Program shall
348
-be treated as though they were included in this License, to the extent
349
-that they are valid under applicable law.  If additional permissions
350
-apply only to part of the Program, that part may be used separately
351
-under those permissions, but the entire Program remains governed by
352
-this License without regard to the additional permissions.
353
-
354
-  When you convey a copy of a covered work, you may at your option
355
-remove any additional permissions from that copy, or from any part of
356
-it.  (Additional permissions may be written to require their own
357
-removal in certain cases when you modify the work.)  You may place
358
-additional permissions on material, added by you to a covered work,
359
-for which you have or can give appropriate copyright permission.
360
-
361
-  Notwithstanding any other provision of this License, for material you
362
-add to a covered work, you may (if authorized by the copyright holders of
363
-that material) supplement the terms of this License with terms:
364
-
365
-    a) Disclaiming warranty or limiting liability differently from the
366
-    terms of sections 15 and 16 of this License; or
367
-
368
-    b) Requiring preservation of specified reasonable legal notices or
369
-    author attributions in that material or in the Appropriate Legal
370
-    Notices displayed by works containing it; or
371
-
372
-    c) Prohibiting misrepresentation of the origin of that material, or
373
-    requiring that modified versions of such material be marked in
374
-    reasonable ways as different from the original version; or
375
-
376
-    d) Limiting the use for publicity purposes of names of licensors or
377
-    authors of the material; or
378
-
379
-    e) Declining to grant rights under trademark law for use of some
380
-    trade names, trademarks, or service marks; or
381
-
382
-    f) Requiring indemnification of licensors and authors of that
383
-    material by anyone who conveys the material (or modified versions of
384
-    it) with contractual assumptions of liability to the recipient, for
385
-    any liability that these contractual assumptions directly impose on
386
-    those licensors and authors.
387
-
388
-  All other non-permissive additional terms are considered "further
389
-restrictions" within the meaning of section 10.  If the Program as you
390
-received it, or any part of it, contains a notice stating that it is
391
-governed by this License along with a term that is a further
392
-restriction, you may remove that term.  If a license document contains
393
-a further restriction but permits relicensing or conveying under this
394
-License, you may add to a covered work material governed by the terms
395
-of that license document, provided that the further restriction does
396
-not survive such relicensing or conveying.
397
-
398
-  If you add terms to a covered work in accord with this section, you
399
-must place, in the relevant source files, a statement of the
400
-additional terms that apply to those files, or a notice indicating
401
-where to find the applicable terms.
402
-
403
-  Additional terms, permissive or non-permissive, may be stated in the
404
-form of a separately written license, or stated as exceptions;
405
-the above requirements apply either way.
406
-
407
-  8. Termination.
408
-
409
-  You may not propagate or modify a covered work except as expressly
410
-provided under this License.  Any attempt otherwise to propagate or
411
-modify it is void, and will automatically terminate your rights under
412
-this License (including any patent licenses granted under the third
413
-paragraph of section 11).
414
-
415
-  However, if you cease all violation of this License, then your
416
-license from a particular copyright holder is reinstated (a)
417
-provisionally, unless and until the copyright holder explicitly and
418
-finally terminates your license, and (b) permanently, if the copyright
419
-holder fails to notify you of the violation by some reasonable means
420
-prior to 60 days after the cessation.
421
-
422
-  Moreover, your license from a particular copyright holder is
423
-reinstated permanently if the copyright holder notifies you of the
424
-violation by some reasonable means, this is the first time you have
425
-received notice of violation of this License (for any work) from that
426
-copyright holder, and you cure the violation prior to 30 days after
427
-your receipt of the notice.
428
-
429
-  Termination of your rights under this section does not terminate the
430
-licenses of parties who have received copies or rights from you under
431
-this License.  If your rights have been terminated and not permanently
432
-reinstated, you do not qualify to receive new licenses for the same
433
-material under section 10.
434
-
435
-  9. Acceptance Not Required for Having Copies.
436
-
437
-  You are not required to accept this License in order to receive or
438
-run a copy of the Program.  Ancillary propagation of a covered work
439
-occurring solely as a consequence of using peer-to-peer transmission
440
-to receive a copy likewise does not require acceptance.  However,
441
-nothing other than this License grants you permission to propagate or
442
-modify any covered work.  These actions infringe copyright if you do
443
-not accept this License.  Therefore, by modifying or propagating a
444
-covered work, you indicate your acceptance of this License to do so.
445
-
446
-  10. Automatic Licensing of Downstream Recipients.
447
-
448
-  Each time you convey a covered work, the recipient automatically
449
-receives a license from the original licensors, to run, modify and
450
-propagate that work, subject to this License.  You are not responsible
451
-for enforcing compliance by third parties with this License.
452
-
453
-  An "entity transaction" is a transaction transferring control of an
454
-organization, or substantially all assets of one, or subdividing an
455
-organization, or merging organizations.  If propagation of a covered
456
-work results from an entity transaction, each party to that
457
-transaction who receives a copy of the work also receives whatever
458
-licenses to the work the party's predecessor in interest had or could
459
-give under the previous paragraph, plus a right to possession of the
460
-Corresponding Source of the work from the predecessor in interest, if
461
-the predecessor has it or can get it with reasonable efforts.
462
-
463
-  You may not impose any further restrictions on the exercise of the
464
-rights granted or affirmed under this License.  For example, you may
465
-not impose a license fee, royalty, or other charge for exercise of
466
-rights granted under this License, and you may not initiate litigation
467
-(including a cross-claim or counterclaim in a lawsuit) alleging that
468
-any patent claim is infringed by making, using, selling, offering for
469
-sale, or importing the Program or any portion of it.
470
-
471
-  11. Patents.
472
-
473
-  A "contributor" is a copyright holder who authorizes use under this
474
-License of the Program or a work on which the Program is based.  The
475
-work thus licensed is called the contributor's "contributor version".
476
-
477
-  A contributor's "essential patent claims" are all patent claims
478
-owned or controlled by the contributor, whether already acquired or
479
-hereafter acquired, that would be infringed by some manner, permitted
480
-by this License, of making, using, or selling its contributor version,
481
-but do not include claims that would be infringed only as a
482
-consequence of further modification of the contributor version.  For
483
-purposes of this definition, "control" includes the right to grant
484
-patent sublicenses in a manner consistent with the requirements of
485
-this License.
486
-
487
-  Each contributor grants you a non-exclusive, worldwide, royalty-free
488
-patent license under the contributor's essential patent claims, to
489
-make, use, sell, offer for sale, import and otherwise run, modify and
490
-propagate the contents of its contributor version.
491
-
492
-  In the following three paragraphs, a "patent license" is any express
493
-agreement or commitment, however denominated, not to enforce a patent
494
-(such as an express permission to practice a patent or covenant not to
495
-sue for patent infringement).  To "grant" such a patent license to a
496
-party means to make such an agreement or commitment not to enforce a
497
-patent against the party.
498
-
499
-  If you convey a covered work, knowingly relying on a patent license,
500
-and the Corresponding Source of the work is not available for anyone
501
-to copy, free of charge and under the terms of this License, through a
502
-publicly available network server or other readily accessible means,
503
-then you must either (1) cause the Corresponding Source to be so
504
-available, or (2) arrange to deprive yourself of the benefit of the
505
-patent license for this particular work, or (3) arrange, in a manner
506
-consistent with the requirements of this License, to extend the patent
507
-license to downstream recipients.  "Knowingly relying" means you have
508
-actual knowledge that, but for the patent license, your conveying the
509
-covered work in a country, or your recipient's use of the covered work
510
-in a country, would infringe one or more identifiable patents in that
511
-country that you have reason to believe are valid.
512
-
513
-  If, pursuant to or in connection with a single transaction or
514
-arrangement, you convey, or propagate by procuring conveyance of, a
515
-covered work, and grant a patent license to some of the parties
516
-receiving the covered work authorizing them to use, propagate, modify
517
-or convey a specific copy of the covered work, then the patent license
518
-you grant is automatically extended to all recipients of the covered
519
-work and works based on it.
520
-
521
-  A patent license is "discriminatory" if it does not include within
522
-the scope of its coverage, prohibits the exercise of, or is
523
-conditioned on the non-exercise of one or more of the rights that are
524
-specifically granted under this License.  You may not convey a covered
525
-work if you are a party to an arrangement with a third party that is
526
-in the business of distributing software, under which you make payment
527
-to the third party based on the extent of your activity of conveying
528
-the work, and under which the third party grants, to any of the
529
-parties who would receive the covered work from you, a discriminatory
530
-patent license (a) in connection with copies of the covered work
531
-conveyed by you (or copies made from those copies), or (b) primarily
532
-for and in connection with specific products or compilations that
533
-contain the covered work, unless you entered into that arrangement,
534
-or that patent license was granted, prior to 28 March 2007.
535
-
536
-  Nothing in this License shall be construed as excluding or limiting
537
-any implied license or other defenses to infringement that may
538
-otherwise be available to you under applicable patent law.
539
-
540
-  12. No Surrender of Others' Freedom.
541
-
542
-  If conditions are imposed on you (whether by court order, agreement or
543
-otherwise) that contradict the conditions of this License, they do not
544
-excuse you from the conditions of this License.  If you cannot convey a
545
-covered work so as to satisfy simultaneously your obligations under this
546
-License and any other pertinent obligations, then as a consequence you may
547
-not convey it at all.  For example, if you agree to terms that obligate you
548
-to collect a royalty for further conveying from those to whom you convey
549
-the Program, the only way you could satisfy both those terms and this
550
-License would be to refrain entirely from conveying the Program.
551
-
552
-  13. Use with the GNU Affero General Public License.
553
-
554
-  Notwithstanding any other provision of this License, you have
555
-permission to link or combine any covered work with a work licensed
556
-under version 3 of the GNU Affero General Public License into a single
557
-combined work, and to convey the resulting work.  The terms of this
558
-License will continue to apply to the part which is the covered work,
559
-but the special requirements of the GNU Affero General Public License,
560
-section 13, concerning interaction through a network will apply to the
561
-combination as such.
562
-
563
-  14. Revised Versions of this License.
564
-
565
-  The Free Software Foundation may publish revised and/or new versions of
566
-the GNU General Public License from time to time.  Such new versions will
567
-be similar in spirit to the present version, but may differ in detail to
568
-address new problems or concerns.
569
-
570
-  Each version is given a distinguishing version number.  If the
571
-Program specifies that a certain numbered version of the GNU General
572
-Public License "or any later version" applies to it, you have the
573
-option of following the terms and conditions either of that numbered
574
-version or of any later version published by the Free Software
575
-Foundation.  If the Program does not specify a version number of the
576
-GNU General Public License, you may choose any version ever published
577
-by the Free Software Foundation.
578
-
579
-  If the Program specifies that a proxy can decide which future
580
-versions of the GNU General Public License can be used, that proxy's
581
-public statement of acceptance of a version permanently authorizes you
582
-to choose that version for the Program.
583
-
584
-  Later license versions may give you additional or different
585
-permissions.  However, no additional obligations are imposed on any
586
-author or copyright holder as a result of your choosing to follow a
587
-later version.
588
-
589
-  15. Disclaimer of Warranty.
590
-
591
-  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592
-APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597
-IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
-
600
-  16. Limitation of Liability.
601
-
602
-  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610
-SUCH DAMAGES.
611
-
612
-  17. Interpretation of Sections 15 and 16.
613
-
614
-  If the disclaimer of warranty and limitation of liability provided
615
-above cannot be given local legal effect according to their terms,
616
-reviewing courts shall apply local law that most closely approximates
617
-an absolute waiver of all civil liability in connection with the
618
-Program, unless a warranty or assumption of liability accompanies a
619
-copy of the Program in return for a fee.
620
-
621
-                     END OF TERMS AND CONDITIONS
622
-
623
-            How to Apply These Terms to Your New Programs
624
-
625
-  If you develop a new program, and you want it to be of the greatest
626
-possible use to the public, the best way to achieve this is to make it
627
-free software which everyone can redistribute and change under these terms.
628
-
629
-  To do so, attach the following notices to the program.  It is safest
630
-to attach them to the start of each source file to most effectively
631
-state the exclusion of warranty; and each file should have at least
632
-the "copyright" line and a pointer to where the full notice is found.
633
-
634
-    <one line to give the program's name and a brief idea of what it does.>
635
-    Copyright (C) <year>  <name of author>
636
-
637
-    This program is free software: you can redistribute it and/or modify
638
-    it under the terms of the GNU General Public License as published by
639
-    the Free Software Foundation, either version 3 of the License, or
640
-    (at your option) any later version.
641
-
642
-    This program is distributed in the hope that it will be useful,
643
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
644
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
645
-    GNU General Public License for more details.
646
-
647
-    You should have received a copy of the GNU General Public License
648
-    along with this program.  If not, see <https://www.gnu.org/licenses/>.
649
-
650
-Also add information on how to contact you by electronic and paper mail.
651
-
652
-  If the program does terminal interaction, make it output a short
653
-notice like this when it starts in an interactive mode:
654
-
655
-    <program>  Copyright (C) <year>  <name of author>
656
-    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657
-    This is free software, and you are welcome to redistribute it
658
-    under certain conditions; type `show c' for details.
659
-
660
-The hypothetical commands `show w' and `show c' should show the appropriate
661
-parts of the General Public License.  Of course, your program's commands
662
-might be different; for a GUI interface, you would use an "about box".
663
-
664
-  You should also get your employer (if you work as a programmer) or school,
665
-if any, to sign a "copyright disclaimer" for the program, if necessary.
666
-For more information on this, and how to apply and follow the GNU GPL, see
667
-<https://www.gnu.org/licenses/>.
668
-
669
-  The GNU General Public License does not permit incorporating your program
670
-into proprietary programs.  If your program is a subroutine library, you
671
-may consider it more useful to permit linking proprietary applications with
672
-the library.  If this is what you want to do, use the GNU Lesser General
673
-Public License instead of this License.  But first, please read
674
-<https://www.gnu.org/licenses/why-not-lgpl.html>.
1
+MIT License
2
+
3
+Copyright (c) 2019 Yattoz
4
+
5
+Permission is hereby granted, free of charge, to any person obtaining a copy
6
+of this software and associated documentation files (the "Software"), to deal
7
+in the Software without restriction, including without limitation the rights
8
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+copies of the Software, and to permit persons to whom the Software is
10
+furnished to do so, subject to the following conditions:
11
+	
12
+The above copyright notice and this permission notice shall be included in all
13
+copies or substantial portions of the Software.
14
+
15
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+SOFTWARE.

+ 9 - 3
app/build.gradle Voir le fichier

@@ -29,11 +29,14 @@ android {
29 29
         applicationId "fr.forum_thalie.tsumugi"
30 30
         minSdkVersion 16
31 31
         targetSdkVersion 29
32
-        versionCode 2
33
-        versionName "1.1dev"
32
+        versionCode 100
33
+        versionName "1.0.0"
34 34
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
35 35
         vectorDrawables.useSupportLibrary = true
36 36
     }
37
+    // Note: I noticed that enabling these make the release app crash on API19-.
38
+    // So I'll disable it as of now for maximum compatibility, even if the app size is a tad bigger.
39
+    /*
37 40
     buildTypes {
38 41
         release {
39 42
             minifyEnabled true
@@ -41,6 +44,7 @@ android {
41 44
             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
42 45
         }
43 46
     }
47
+     */
44 48
 }
45 49
 
46 50
 dependencies {
@@ -65,7 +69,9 @@ dependencies {
65 69
      */
66 70
 
67 71
     implementation "androidx.media:media:1.1.0"
68
-    implementation 'com.google.android.exoplayer:exoplayer:2.11.0'
72
+    //implementation 'com.google.android.exoplayer:exoplayer:2.11.1'
73
+    implementation project(':exoplayer-library') // uses local ExoPlayer clone, from dev-v2 branch (fixes ISO-8859-1 ICY metadata
74
+
69 75
     implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
70 76
     implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0'
71 77
 

BIN
app/src/main/assets/the_stream_is_down.mp3 Voir le fichier


BIN
app/src/main/ic_launcher-web.png Voir le fichier


+ 2 - 2
app/src/main/java/fr/forum_thalie/tsumugi/BaseNotification.kt Voir le fichier

@@ -68,8 +68,8 @@ abstract class BaseNotification(private val notificationChannelId: String,
68 68
         builder = NotificationCompat.Builder(c, channelID)
69 69
 
70 70
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
71
-            builder.setSmallIcon(R.drawable.lollipop_logo)
72
-            builder.color = -0xf58b01 // same color as Accent. Can't use c.getColor since it's API23+
71
+            builder.setSmallIcon(R.drawable.ic_notif_lollipop_icon)
72
+            builder.color = 0xf58b01 // same color as Accent. Can't use c.getColor since it's API23+
73 73
         } else {
74 74
             builder.setSmallIcon(R.drawable.logo_roundsquare)
75 75
         }

+ 6 - 3
app/src/main/java/fr/forum_thalie/tsumugi/RadioService.kt Voir le fichier

@@ -281,17 +281,18 @@ class RadioService : MediaBrowserServiceCompat() {
281 281
         PlayerStore.instance.isServiceStarted.value = false
282 282
         PlayerStore.instance.isInitialized = false
283 283
 
284
+
285
+        RadioSleeper.instance.cancelSleep(this, isClosing = true)
286
+
284 287
         PreferenceManager.getDefaultSharedPreferences(this).edit {
285 288
             this.putBoolean("isSleeping", false)
286 289
             this.commit()
287 290
         }
288
-        RadioSleeper.instance.cancelSleep(this)
289 291
 
290 292
         apiTicker.cancel() // stops the timer.
291 293
         Log.d(tag, radioTag + "destroyed")
292 294
         // if the service is destroyed, the application had become useless.
293
-        // exitProcess(0)
294
-        Process.killProcess(Process.myPid())
295
+        exitProcess(0)
295 296
     }
296 297
 
297 298
     // ########################################
@@ -350,10 +351,12 @@ class RadioService : MediaBrowserServiceCompat() {
350 351
             setBufferDurationsMs(minBufferMillis, maxBufferMillis, bufferForPlayback, bufferForPlaybackAfterRebuffer)
351 352
         }.createDefaultLoadControl()
352 353
 
354
+
353 355
         val playerBuilder = SimpleExoPlayer.Builder(this)
354 356
         playerBuilder.setLoadControl(loadControl)
355 357
         player = playerBuilder.build()
356 358
 
359
+
357 360
         player.addMetadataOutput {
358 361
             for (i in 0 until it.length()) {
359 362
                 val entry  = it.get(i)

+ 2 - 1
app/src/main/java/fr/forum_thalie/tsumugi/Values.kt Voir le fichier

@@ -8,7 +8,8 @@ const val tag = "fr.forum_thalie.tsumugi"
8 8
 const val noConnectionValue = "—"
9 9
 const val streamDownValue = "Tsumugi est HS !" // we don't want this value to be displaed in the "last played" screen.
10 10
 val weekdaysArray : Array<String> = arrayOf( "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche")
11
-
11
+const val newsDateTimePattern = "EEE, d MMM yyyy HH:mm:ss Z"
12
+const val newsDisplayDatePattern = "dd MMM yyyy"
12 13
 // Below this line is only automatically programmed values. Unless your week does not start with Monday, you don't need to change this.
13 14
 
14 15
 val weekdays = ArrayList<String>().apply { weekdaysArray.forEach { add(it) } }

+ 21 - 18
app/src/main/java/fr/forum_thalie/tsumugi/alarm/RadioAlarm.kt Voir le fichier

@@ -19,29 +19,39 @@ class RadioAlarm {
19 19
             RadioAlarm()
20 20
         }
21 21
     }
22
-    lateinit var alarmIntent: PendingIntent
23 22
 
23
+    private lateinit var alarmIntent: PendingIntent
24
+    private lateinit var showIntent: PendingIntent
24 25
 
25
-    fun cancelAlarm(c: Context)
26
+    private fun defineIntents(c: Context)
26 27
     {
27
-        if (::alarmIntent.isInitialized)
28
-        {
29
-            val alarmManager = c.getSystemService(Context.ALARM_SERVICE) as AlarmManager
30
-            alarmManager.cancel(alarmIntent)
28
+        alarmIntent = Intent(c, BootBroadcastReceiver::class.java).let { intent ->
29
+            intent.putExtra("action", "$tag.${Actions.PLAY_OR_FALLBACK.name}")
30
+            PendingIntent.getBroadcast(c, 0, intent, 0)
31
+        }
32
+        showIntent = Intent(c, ParametersActivity::class.java).let { intent ->
33
+            intent.putExtra("action", "alarm")
34
+            PendingIntent.getActivity(c, 0, intent, 0)
31 35
         }
32 36
     }
33 37
 
38
+
39
+    fun cancelAlarm(c: Context)
40
+    {
41
+        defineIntents(c)
42
+        val alarmManager = c.getSystemService(Context.ALARM_SERVICE) as AlarmManager
43
+        alarmManager.cancel(alarmIntent)
44
+    }
45
+
34 46
     fun setNextAlarm(c: Context, isForce: Boolean = false, forceTime: Int? = null, forceDays: Set<String>? = null)
35 47
     {
48
+        defineIntents(c)
36 49
         // don't do anything if the preference is set to FALSE, of course.
37 50
         if (!PreferenceManager.getDefaultSharedPreferences(c).getBoolean("isWakingUp", false) && !isForce)
38 51
             return
39 52
 
40 53
         val alarmManager = c.getSystemService(Context.ALARM_SERVICE) as AlarmManager
41
-        alarmIntent = Intent(c, BootBroadcastReceiver::class.java).let { intent ->
42
-            intent.putExtra("action", "$tag.${Actions.PLAY_OR_FALLBACK.name}")
43
-            PendingIntent.getBroadcast(c, 0, intent, 0)
44
-        }
54
+
45 55
         val showIntent = Intent(c, ParametersActivity::class.java).let { intent ->
46 56
             intent.putExtra("action", ActionOpenParam.ALARM.name)
47 57
             PendingIntent.getActivity(c, 0, intent, 0)
@@ -95,19 +105,12 @@ class RadioAlarm {
95 105
 
96 106
     fun snooze(c: Context)
97 107
     {
108
+        defineIntents(c)
98 109
         val snoozeString = preferenceStore.getString("snoozeDuration", "10") ?: "10"
99 110
         val snoozeMinutes = if (snoozeString == c.getString(R.string.disable)) 0  else Integer.parseInt(snoozeString)
100 111
         if (snoozeMinutes > 0)
101 112
         {
102 113
             val alarmManager = c.getSystemService(Context.ALARM_SERVICE) as AlarmManager
103
-            alarmIntent = Intent(c, BootBroadcastReceiver::class.java).let { intent ->
104
-                intent.putExtra("action", "$tag.${Actions.PLAY_OR_FALLBACK.name}")
105
-                PendingIntent.getBroadcast(c, 0, intent, 0)
106
-            }
107
-            val showIntent = Intent(c, ParametersActivity::class.java).let { intent ->
108
-                intent.putExtra("action", "alarm")
109
-                PendingIntent.getActivity(c, 0, intent, 0)
110
-            }
111 114
 
112 115
             AlarmManagerCompat.setAlarmClock(alarmManager, Calendar.getInstance().timeInMillis + (snoozeMinutes * 60 * 1000), showIntent, alarmIntent)
113 116
 

+ 24 - 16
app/src/main/java/fr/forum_thalie/tsumugi/alarm/RadioSleeper.kt Voir le fichier

@@ -30,8 +30,21 @@ class RadioSleeper {
30 30
     private lateinit var sleepIntent: PendingIntent
31 31
     private lateinit var fadeOutIntent: PendingIntent
32 32
 
33
+    private fun defineIntents(c: Context)
34
+    {
35
+        sleepIntent = Intent(c, RadioService::class.java).let { intent ->
36
+            intent.putExtra("action", Actions.KILL.name)
37
+            PendingIntent.getService(c, 99, intent, 0)
38
+        }
39
+        fadeOutIntent = Intent(c, RadioService::class.java).let { intent ->
40
+            intent.putExtra("action", Actions.FADE_OUT.name)
41
+            PendingIntent.getService(c, 98, intent, 0)
42
+        }
43
+    }
44
+
33 45
     fun setSleep(c: Context, isForce: Boolean = false, forceDuration: Long? = null)
34 46
     {
47
+        defineIntents(c)
35 48
         // don't do anything if the preference is set to FALSE, of course.
36 49
         if (!PreferenceManager.getDefaultSharedPreferences(c).getBoolean("isSleeping", false) && !isForce)
37 50
             return
@@ -39,19 +52,13 @@ class RadioSleeper {
39 52
         val minutes: Long = forceDuration ?: Integer.parseInt(PreferenceManager.getDefaultSharedPreferences(c).getString("sleepDuration", "1") ?: "1").toLong()
40 53
 
41 54
         val alarmManager = c.getSystemService(Context.ALARM_SERVICE) as AlarmManager
42
-        sleepIntent = Intent(c, RadioService::class.java).let { intent ->
43
-            intent.putExtra("action", Actions.KILL.name)
44
-            PendingIntent.getService(c, 99, intent, 0)
45
-        }
55
+
46 56
 
47 57
         val currentMillis = System.currentTimeMillis()
48 58
         if (minutes > 0)
49 59
         {
50 60
             AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, currentMillis + (minutes * 60 * 1000),  sleepIntent)
51
-            fadeOutIntent = Intent(c, RadioService::class.java).let { intent ->
52
-                intent.putExtra("action", Actions.FADE_OUT.name)
53
-                PendingIntent.getService(c, 98, intent, 0)
54
-            }
61
+
55 62
             AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, currentMillis + (minutes * 60 * 1000) - (1 * 60 * 1000), fadeOutIntent)
56 63
             sleepAtMillis.value = System.currentTimeMillis() + (minutes * 60 * 1000) - 1 // this -1 allows to round the division for display at the right integer
57 64
             Log.d(tag, "set sleep to $minutes minutes")
@@ -59,19 +66,20 @@ class RadioSleeper {
59 66
     }
60 67
 
61 68
 
62
-    fun cancelSleep(c: Context)
69
+    fun cancelSleep(c: Context, isClosing: Boolean = false)
63 70
     {
64
-        if (::sleepIntent.isInitialized)
65
-        {
66
-            val alarmManager = c.getSystemService(Context.ALARM_SERVICE) as AlarmManager
67
-            alarmManager.cancel(sleepIntent)
68
-            alarmManager.cancel(fadeOutIntent)
71
+        defineIntents(c)
72
+        val alarmManager = c.getSystemService(Context.ALARM_SERVICE) as AlarmManager
73
+        alarmManager.cancel(sleepIntent)
74
+        alarmManager.cancel(fadeOutIntent)
69 75
 
76
+        if (!isClosing)
77
+        {
70 78
             val cancelFadeOutIntent = Intent(c, RadioService::class.java).putExtra("action", Actions.CANCEL_FADE_OUT.name)
71 79
             c.startService(cancelFadeOutIntent)
72
-
73
-            Log.d(tag, "cancelled sleep")
74 80
         }
81
+
82
+        Log.d(tag, "cancelled sleep")
75 83
         sleepAtMillis.value = null
76 84
     }
77 85
 }

+ 27 - 15
app/src/main/java/fr/forum_thalie/tsumugi/ui/news/NewsAdapter.kt Voir le fichier

@@ -21,6 +21,7 @@ import androidx.core.text.HtmlCompat
21 21
 import androidx.core.widget.TextViewCompat
22 22
 import androidx.recyclerview.widget.RecyclerView
23 23
 import fr.forum_thalie.tsumugi.R
24
+import fr.forum_thalie.tsumugi.newsDisplayDatePattern
24 25
 import java.io.IOException
25 26
 import java.io.InputStream
26 27
 import java.net.URL
@@ -84,7 +85,7 @@ class ImageGetterAsyncTask(
84 85
 
85 86
 }
86 87
 
87
-class NewsAdapter(private val dataSet: ArrayList<News>, private val c: Context
88
+class NewsAdapter(private val dataSet: ArrayList<News>, private val c: Context, private val vm: NewsViewModel
88 89
     /*,
89 90
     context: Context,
90 91
     resource: Int,
@@ -125,23 +126,34 @@ class NewsAdapter(private val dataSet: ArrayList<News>, private val c: Context
125 126
 
126 127
         header.text = HtmlCompat.fromHtml(dataSet[position].header, HtmlCompat.FROM_HTML_MODE_LEGACY).replace(Regex("\n"), " ")
127 128
         author.text = "| ${dataSet[position].author}"
128
-        val sdf = SimpleDateFormat("dd MMM yyyy", Locale.getDefault())
129
+        val sdf = SimpleDateFormat(newsDisplayDatePattern, Locale.getDefault())
129 130
         date.text = sdf.format(dataSet[position].date)
130 131
         TextViewCompat.setAutoSizeTextTypeWithDefaults(author, TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM)
131 132
 
132
-        val spanned = HtmlCompat.fromHtml(
133
-            dataSet[position].text,
134
-            HtmlCompat.FROM_HTML_MODE_LEGACY,
135
-            ImageGetter { source ->
136
-                val d = LevelListDrawable()
137
-                val empty: Drawable? = ContextCompat.getDrawable(c, R.drawable.exo_icon_circular_play)
138
-
139
-                d.addLevel(0, 0, empty!!)
140
-                d.setBounds(0, 0, empty.intrinsicWidth, empty.intrinsicHeight)
141
-                ImageGetterAsyncTask(c, source, d).execute(text)
142
-                d
143
-            }, null
144
-        )
133
+        val spanned = // the trick is to avoid loading images when the adapter is called with preloading.
134
+            if (vm.isPreLoadingNews) {
135
+                HtmlCompat.fromHtml(
136
+                    dataSet[position].text,
137
+                    HtmlCompat.FROM_HTML_MODE_LEGACY)
138
+            } else {
139
+                HtmlCompat.fromHtml(
140
+                    dataSet[position].text,
141
+                    HtmlCompat.FROM_HTML_MODE_LEGACY,
142
+                    ImageGetter { source ->
143
+                        val d = LevelListDrawable()
144
+                        /*
145
+                        val empty: Drawable? = ContextCompat.getDrawable(c, R.drawable.exo_icon_play)
146
+                        d.addLevel(0, 0, empty!!)
147
+                        d.setBounds(0, 0, empty.intrinsicWidth, empty.intrinsicHeight)
148
+                         */
149
+                        ImageGetterAsyncTask(c, source, d).execute(text)
150
+                        d
151
+                    }, null
152
+                )
153
+            }
154
+
155
+
156
+
145 157
         text.text = spanned
146 158
         text.movementMethod = LinkMovementMethod.getInstance()
147 159
     }

+ 2 - 2
app/src/main/java/fr/forum_thalie/tsumugi/ui/news/NewsFragment.kt Voir le fichier

@@ -58,7 +58,7 @@ class NewsFragment : Fragment() {
58 58
         newsViewModel.root = inflater.inflate(R.layout.fragment_news, container, false) as SwipeRefreshLayout
59 59
 
60 60
         viewManager = LinearLayoutManager(context)
61
-        viewAdapter = NewsAdapter(newsViewModel.newsArray, context!!)
61
+        viewAdapter = NewsAdapter(newsViewModel.newsArray, context!!, newsViewModel)
62 62
         recyclerView = newsViewModel.root.findViewById<RecyclerView>(R.id.news_recycler).apply {
63 63
             // use this setting to improve performance if you know that changes
64 64
             // in content do not change the layout size of the RecyclerView
@@ -100,7 +100,7 @@ class NewsFragment : Fragment() {
100 100
         newsViewModel =
101 101
             ViewModelProviders.of(this).get(NewsViewModel::class.java)
102 102
 
103
-        newsViewModel.fetch(c = context!!)
103
+        newsViewModel.fetch(c = context!!, isPreloading = true)
104 104
         Log.d(tag, "news fetched onCreate")
105 105
         super.onCreate(savedInstanceState)
106 106
     }

+ 6 - 7
app/src/main/java/fr/forum_thalie/tsumugi/ui/news/NewsViewModel.kt Voir le fichier

@@ -8,16 +8,13 @@ import android.webkit.WebView
8 8
 import androidx.lifecycle.ViewModel
9 9
 import androidx.recyclerview.widget.RecyclerView
10 10
 import com.prof.rssparser.Parser
11
-import fr.forum_thalie.tsumugi.Async
12 11
 import fr.forum_thalie.tsumugi.R
12
+import fr.forum_thalie.tsumugi.newsDateTimePattern
13 13
 import fr.forum_thalie.tsumugi.tag
14 14
 import kotlinx.coroutines.CoroutineScope
15 15
 import kotlinx.coroutines.Dispatchers
16 16
 import kotlinx.coroutines.Job
17 17
 import kotlinx.coroutines.launch
18
-import org.json.JSONArray
19
-import org.json.JSONObject
20
-import java.net.URL
21 18
 import java.text.SimpleDateFormat
22 19
 import java.util.*
23 20
 import kotlin.collections.ArrayList
@@ -30,6 +27,7 @@ class NewsViewModel : ViewModel() {
30 27
     lateinit var root: View
31 28
     var webView: WebView? = null
32 29
     var webViewNews: WebViewNews? = null
30
+    var isPreLoadingNews = false
33 31
 
34 32
     val newsArray : ArrayList<News> = ArrayList()
35 33
     var isWebViewLoaded = false
@@ -37,7 +35,7 @@ class NewsViewModel : ViewModel() {
37 35
     private val viewModelJob = Job()
38 36
     private val coroutineScope = CoroutineScope(Dispatchers.Main + viewModelJob)
39 37
 
40
-    fun fetch(root: androidx.swiperefreshlayout.widget.SwipeRefreshLayout? = null, viewAdapter: RecyclerView.Adapter<*>? = null, c: Context)
38
+    fun fetch(root: androidx.swiperefreshlayout.widget.SwipeRefreshLayout? = null, viewAdapter: RecyclerView.Adapter<*>? = null, c: Context, isPreloading: Boolean = false)
41 39
     {
42 40
         val urlToScrape = c.getString(R.string.rss_url)
43 41
         if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT)
@@ -60,9 +58,9 @@ class NewsViewModel : ViewModel() {
60 58
                     news.text = item.content ?: ""
61 59
                     news.header = item.description ?: ""
62 60
 
63
-                    val formatter6 = SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH)
61
+                    val formatter6 = SimpleDateFormat(newsDateTimePattern, Locale.ENGLISH)
64 62
                     val dateString = item.pubDate.toString()
65
-                    Log.d(tag, "$news --- ${dateString}")
63
+                    Log.d(tag, "$news --- $dateString")
66 64
 
67 65
                     news.date = formatter6.parse(dateString) ?: Date(0)
68 66
 
@@ -70,6 +68,7 @@ class NewsViewModel : ViewModel() {
70 68
                 }
71 69
                 // The list contains all article's data. For example you can use it for your adapter.
72 70
                 root?.isRefreshing = false
71
+                isPreLoadingNews = isPreloading
73 72
                 viewAdapter?.notifyDataSetChanged()
74 73
             }catch (e: Exception)
75 74
             {

Fichier diff supprimé car celui-ci est trop grand
+ 11 - 0
app/src/main/res/drawable-anydpi/ic_settings.xml


BIN
app/src/main/res/drawable-hdpi/ic_notif_lollipop_icon.png Voir le fichier


BIN
app/src/main/res/drawable-hdpi/ic_settings.png Voir le fichier


BIN
app/src/main/res/drawable-mdpi/ic_notif_lollipop_icon.png Voir le fichier


BIN
app/src/main/res/drawable-mdpi/ic_settings.png Voir le fichier


BIN
app/src/main/res/drawable-xhdpi/ic_notif_lollipop_icon.png Voir le fichier


BIN
app/src/main/res/drawable-xhdpi/ic_settings.png Voir le fichier


BIN
app/src/main/res/drawable-xxhdpi/ic_notif_lollipop_icon.png Voir le fichier


BIN
app/src/main/res/drawable-xxhdpi/ic_settings.png Voir le fichier


BIN
app/src/main/res/drawable-xxxhdpi/ic_notif_lollipop_icon.png Voir le fichier


+ 3 - 3
app/src/main/res/layout/fragment_nowplaying.xml Voir le fichier

@@ -30,13 +30,13 @@
30 30
         <ImageView
31 31
             android:id="@+id/streamerPicture"
32 32
             android:layout_width="0dp"
33
-            android:layout_height="wrap_content"
33
+            android:layout_height="0dp"
34 34
             android:layout_gravity="top|center_horizontal"
35 35
             android:adjustViewBounds="true"
36 36
             android:contentDescription="dj-image"
37
-            android:scaleType="fitCenter"
37
+            android:scaleType="fitStart"
38 38
             app:layout_constraintEnd_toEndOf="parent"
39
-
39
+            app:layout_constraintBottom_toBottomOf="parent"
40 40
             app:layout_constraintStart_toStartOf="@id/imageGuideline"
41 41
             app:layout_constraintTop_toTopOf="parent"
42 42
             app:srcCompat="@drawable/logo_roundsquare"

+ 2 - 1
app/src/main/res/menu/toolbar_menu.xml Voir le fichier

@@ -30,7 +30,8 @@
30 30
 
31 31
     <item android:id="@+id/action_settings"
32 32
         android:title="@string/action_settings"
33
-        app:showAsAction="never"/>
33
+        android:icon="@drawable/ic_settings"
34
+        app:showAsAction="ifRoom"/>
34 35
 
35 36
 
36 37
 </menu>

+ 1 - 1
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml Voir le fichier

@@ -1,5 +1,5 @@
1 1
 <?xml version="1.0" encoding="utf-8"?>
2 2
 <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
3 3
     <background android:drawable="@color/ic_launcher_background"/>
4
-    <foreground android:drawable="@drawable/ic_launcher_foreground"/>
4
+    <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
5 5
 </adaptive-icon>

+ 1 - 1
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml Voir le fichier

@@ -1,5 +1,5 @@
1 1
 <?xml version="1.0" encoding="utf-8"?>
2 2
 <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
3 3
     <background android:drawable="@color/ic_launcher_background"/>
4
-    <foreground android:drawable="@drawable/ic_launcher_foreground"/>
4
+    <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
5 5
 </adaptive-icon>

BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png Voir le fichier


BIN
app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png Voir le fichier


BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.png Voir le fichier


BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png Voir le fichier


BIN
app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png Voir le fichier


BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.png Voir le fichier


BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png Voir le fichier


BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png Voir le fichier


BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png Voir le fichier


BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png Voir le fichier


BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png Voir le fichier


BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png Voir le fichier


BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png Voir le fichier


BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png Voir le fichier


BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png Voir le fichier


+ 2 - 16
app/src/main/res/values-fr/strings.xml Voir le fichier

@@ -8,11 +8,6 @@
8 8
 
9 9
     <string name="now_playing_notification_title_template">Maintenant: %1$s</string>
10 10
 
11
-    <string name="MEDIA_ROOT_ID">radio_root_id</string>
12
-    <string name="STREAM_URL_RADIO">https://relay0.r-a-d.io/main.mp3</string>
13
-    <string name="STREAM_URL_TSUMUGI">https://radio.mahoro-net.org/streams/tsumugi</string>
14
-    <string name="STREAM_URL_RSTLSS">http://stream.radiosolution.fr/rstlss.mp3</string>
15
-
16 11
     <string name="volume">Volume : </string>
17 12
 
18 13
     <string name="up_next">Émission en cours :</string>
@@ -20,11 +15,6 @@
20 15
     <string name="error_webView">Erreur du chargement de WebView. Téléchargez Google Chrome sur le Play Store, ou activez le si vous l\'avez désactivé.</string>
21 16
     <string name="action_settings">Paramètres</string>
22 17
     <string name="action_bug_submit">Reporter un bug (GitHub)</string>
23
-    <string name="github_url_new_issue">https://github.com/yattoz/Tsumugi-app/issues/</string>
24
-
25
-    <string name="nowPlayingNotificationChannel">Tsumugi Stream Service</string>
26
-    <string name="nowPlayingChannelId">fr.forum_thalie.tsumugi.PLAYER_SERVICE</string>
27
-
28 18
     <string name="snackbarPersistent">Restent visibles, peuvent être fermées avec un bouton \"OK\" ou en glissant.</string>
29 19
     <string name="snackbarNonPersistent">Disparaissent après quelques instants</string>
30 20
     <string name="every_day">Tous les jours</string>
@@ -37,20 +27,16 @@
37 27
     <string name="action_sleep">Minuterie avant fermeture</string>
38 28
     <string name="dont_fetch_on_background">Désactiver</string>
39 29
     <string name="restart_the_app">Vous devez redémarrer l\'application pour valider ces changements.</string>
40
-
41 30
     <string name="action_alarm">Alarme</string>
42 31
     <string name="sleep_fade_out_text">Une minute avant la fin de la minuterie, le volume va décroitre progressivement.</string>
43 32
     <string name="disable">Désactiver</string>
44
-    <string name="website_url">https://tsumugi.forum-thalie.fr/</string>
45
-    <string name="rss_url">https://tsumugi.forum-thalie.fr/?feed=rss2</string>
46
-    <string name="planning_url">ADD SOME URL HERE</string>
47 33
     <string name="select_one_day">Sélectionner au moins un jour.</string>
48 34
     <string name="no_alarm_set">Pas d\'alarme</string>
49 35
     <string name="next_alarm">Prochaine alarme :</string>
50
-    <string name="lp">Dernières titres</string>
36
+    <string name="lp">Derniers titres</string>
51 37
     <string name="programme">Planning</string>
52 38
     <string name="regular_programme">Programme régulier</string>
53
-    <string name="useAlarmClock">Activer l\alarme</string>
39
+    <string name="useAlarmClock">Activer l\'alarme</string>
54 40
     <string name="setTime">Choisir l\'heure</string>
55 41
     <string name="selectDaysOfWeek">Choisir les jours</string>
56 42
     <string name="SetSnoozeDuration">Choisir le délai de snooze (minutes)</string>

+ 6 - 0
app/src/main/res/values-v21/strings.xml Voir le fichier

@@ -0,0 +1,6 @@
1
+<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
2
+
3
+    <!-- URLs -->
4
+    <string name="STREAM_URL_TSUMUGI">https://radio.mahoro-net.org/streams/tsumugi</string>
5
+
6
+</resources>

+ 13 - 8
app/src/main/res/values/strings.xml Voir le fichier

@@ -1,4 +1,15 @@
1 1
 <resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
2
+
3
+    <!-- URLs -->
4
+    <string name="STREAM_URL_RADIO">https://relay0.r-a-d.io/main.mp3</string>
5
+    <string name="STREAM_URL_TSUMUGI">http://shelter.mahoro-net.org:8000/tsumugi</string>
6
+    <string name="STREAM_URL_RSTLSS">http://stream.radiosolution.fr/rstlss.mp3</string>
7
+    <string name="github_url_new_issue">https://github.com/yattoz/Tsumugi-app/issues/</string>
8
+    <string name="website_url">https://tsumugi.forum-thalie.fr/</string>
9
+    <string name="rss_url">https://tsumugi.forum-thalie.fr/?feed=rss2</string>
10
+    <string name="planning_url">ADD SOME URL HERE</string>
11
+
12
+
2 13
     <string name="app_name">Tsumugi</string>
3 14
     <string name="title_nowplaying">Tsumugi</string>
4 15
     <string name="title_queue_lp">Songs</string>
@@ -9,9 +20,7 @@
9 20
     <string name="now_playing_notification_title_template">Now playing: %1$s</string>
10 21
 
11 22
     <string name="MEDIA_ROOT_ID">radio_root_id</string>
12
-    <string name="STREAM_URL_RADIO">https://relay0.r-a-d.io/main.mp3</string>
13
-    <string name="STREAM_URL_TSUMUGI">https://radio.mahoro-net.org/streams/tsumugi</string>
14
-    <string name="STREAM_URL_RSTLSS">http://stream.radiosolution.fr/rstlss.mp3</string>
23
+
15 24
 
16 25
     <string name="volume">Volume: </string>
17 26
 
@@ -20,9 +29,8 @@
20 29
     <string name="error_webView">Error loading WebView. Try downloading Google Chrome on Google Play, or enabling it if you disabled it.</string>
21 30
     <string name="action_settings">Settings</string>
22 31
     <string name="action_bug_submit">Submit a bug (GitHub)</string>
23
-    <string name="github_url_new_issue">https://github.com/yattoz/Tsumugi-app/issues/</string>
24 32
 
25
-    <string name="nowPlayingNotificationChannel">R/a/dio Stream Service</string>
33
+    <string name="nowPlayingNotificationChannel">Tsumugi Stream Service</string>
26 34
     <string name="nowPlayingChannelId">fr.forum_thalie.tsumugi.PLAYER_SERVICE</string>
27 35
 
28 36
     <string name="snackbarPersistent">Stay visible, can be closed with \"OK\" button</string>
@@ -41,9 +49,6 @@
41 49
     <string name="action_alarm">Alarm</string>
42 50
     <string name="sleep_fade_out_text">One minute before the end of the timer, the volume will gradually decrease.</string>
43 51
     <string name="disable">Disable</string>
44
-    <string name="website_url">https://tsumugi.forum-thalie.fr/</string>
45
-    <string name="rss_url">https://tsumugi.forum-thalie.fr/?feed=rss2</string>
46
-    <string name="planning_url">ADD SOME URL HERE</string>
47 52
     <string name="select_one_day">Select at least one day</string>
48 53
     <string name="no_alarm_set">No alarm set</string>
49 54
     <string name="next_alarm">Next alarm:</string>

+ 4 - 0
settings.gradle Voir le fichier

@@ -1,2 +1,6 @@
1 1
 include ':app'
2 2
 rootProject.name='Tsumugi-app'
3
+
4
+gradle.ext.exoplayerRoot = './ExoPlayer'
5
+gradle.ext.exoplayerModulePrefix = 'exoplayer-'
6
+apply from: new File(gradle.ext.exoplayerRoot, 'core_settings.gradle')