| ... | ... |
@@ -0,0 +1 @@ |
| 1 |
+/build |
| ... | ... |
@@ -0,0 +1,38 @@ |
| 1 |
+apply plugin: 'com.android.application' |
|
| 2 |
+ |
|
| 3 |
+android {
|
|
| 4 |
+ compileSdkVersion 22 |
|
| 5 |
+ buildToolsVersion '25.0.0' |
|
| 6 |
+ |
|
| 7 |
+ defaultConfig {
|
|
| 8 |
+ applicationId "com.yc.rss.radio" |
|
| 9 |
+ minSdkVersion 19 |
|
| 10 |
+ targetSdkVersion 20 |
|
| 11 |
+ versionCode 20170617 |
|
| 12 |
+ versionName "1.0.17" |
|
| 13 |
+ } |
|
| 14 |
+ buildTypes {
|
|
| 15 |
+ release {
|
|
| 16 |
+ applicationIdSuffix ".release" |
|
| 17 |
+ minifyEnabled true |
|
| 18 |
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
| 19 |
+ } |
|
| 20 |
+ debug {
|
|
| 21 |
+ applicationIdSuffix ".debug" |
|
| 22 |
+ minifyEnabled false |
|
| 23 |
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
| 24 |
+ } |
|
| 25 |
+ } |
|
| 26 |
+ dexOptions {
|
|
| 27 |
+ incremental true |
|
| 28 |
+ } |
|
| 29 |
+ compileOptions {
|
|
| 30 |
+ sourceCompatibility JavaVersion.VERSION_1_7 |
|
| 31 |
+ targetCompatibility JavaVersion.VERSION_1_7 |
|
| 32 |
+ } |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+dependencies {
|
|
| 36 |
+ compile fileTree(include: ['*.jar'], dir: 'libs') |
|
| 37 |
+ compile 'com.android.support:appcompat-v7:22.2.1' |
|
| 38 |
+} |
| ... | ... |
@@ -0,0 +1,17 @@ |
| 1 |
+# Add project specific ProGuard rules here. |
|
| 2 |
+# By default, the flags in this file are appended to flags specified |
|
| 3 |
+# in /home/cawidrone/Android/Sdk/tools/proguard/proguard-android.txt |
|
| 4 |
+# You can edit the include path and order by changing the proguardFiles |
|
| 5 |
+# directive in build.gradle. |
|
| 6 |
+# |
|
| 7 |
+# For more details, see |
|
| 8 |
+# http://developer.android.com/guide/developing/tools/proguard.html |
|
| 9 |
+ |
|
| 10 |
+# Add any project specific keep options here: |
|
| 11 |
+ |
|
| 12 |
+# If your project uses WebView with JS, uncomment the following |
|
| 13 |
+# and specify the fully qualified class name to the JavaScript interface |
|
| 14 |
+# class: |
|
| 15 |
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
|
| 16 |
+# public *; |
|
| 17 |
+#} |
| ... | ... |
@@ -0,0 +1,13 @@ |
| 1 |
+package com.yc.rss.marianne; |
|
| 2 |
+ |
|
| 3 |
+import android.app.Application; |
|
| 4 |
+import android.test.ApplicationTestCase; |
|
| 5 |
+ |
|
| 6 |
+/** |
|
| 7 |
+ * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a> |
|
| 8 |
+ */ |
|
| 9 |
+public class ApplicationTest extends ApplicationTestCase<Application> {
|
|
| 10 |
+ public ApplicationTest() {
|
|
| 11 |
+ super(Application.class); |
|
| 12 |
+ } |
|
| 13 |
+} |
| ... | ... |
@@ -0,0 +1,26 @@ |
| 1 |
+<?xml version="1.0" encoding="utf-8"?> |
|
| 2 |
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
|
| 3 |
+ package="com.yc.rss.radio"> |
|
| 4 |
+ <uses-permission android:name="android.permission.INTERNET" /> |
|
| 5 |
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> |
|
| 6 |
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> |
|
| 7 |
+ |
|
| 8 |
+ <application |
|
| 9 |
+ android:allowBackup="true" |
|
| 10 |
+ android:icon="@mipmap/ic_launcher" |
|
| 11 |
+ android:logo="@drawable/ic_launcher" |
|
| 12 |
+ android:label="@string/app_name" |
|
| 13 |
+ android:theme="@style/AppTheme" |
|
| 14 |
+ android:hardwareAccelerated="true" |
|
| 15 |
+ android:screenOrientation="portrait" > |
|
| 16 |
+ <activity |
|
| 17 |
+ android:name=".MainActivity" |
|
| 18 |
+ android:label="@string/app_name" > |
|
| 19 |
+ |
|
| 20 |
+ <intent-filter> |
|
| 21 |
+ <action android:name="android.intent.action.MAIN" /> |
|
| 22 |
+ <category android:name="android.intent.category.LAUNCHER" /> |
|
| 23 |
+ </intent-filter> |
|
| 24 |
+ </activity> |
|
| 25 |
+ </application> |
|
| 26 |
+</manifest> |
| ... | ... |
@@ -0,0 +1,161 @@ |
| 1 |
+<?xml version='1.0' encoding='UTF-8'?> |
|
| 2 |
+<channel_list> |
|
| 3 |
+ <channel> |
|
| 4 |
+ <item> |
|
| 5 |
+ <title>France Info</title> |
|
| 6 |
+ <mp3>https://files.kawi.fr:8000/finfo</mp3> |
|
| 7 |
+ <shortname>finfo</shortname> |
|
| 8 |
+ <icy>0</icy> |
|
| 9 |
+ </item> |
|
| 10 |
+ <item> |
|
| 11 |
+ <title>France Inter</title> |
|
| 12 |
+ <mp3>https://files.kawi.fr:8000/finter</mp3> |
|
| 13 |
+ <shortname>finter</shortname> |
|
| 14 |
+ <icy>0</icy> |
|
| 15 |
+ </item> |
|
| 16 |
+ <item> |
|
| 17 |
+ <title>France Culture</title> |
|
| 18 |
+ <mp3>https://files.kawi.fr:8000/fculture</mp3> |
|
| 19 |
+ <shortname>fculture</shortname> |
|
| 20 |
+ <icy>0</icy> |
|
| 21 |
+ </item> |
|
| 22 |
+ <item> |
|
| 23 |
+ <title>France Musique</title> |
|
| 24 |
+ <mp3>https://files.kawi.fr:8000/fmusique128</mp3> |
|
| 25 |
+ <shortname>fmusique</shortname> |
|
| 26 |
+ <icy>0</icy> |
|
| 27 |
+ </item> |
|
| 28 |
+ <item> |
|
| 29 |
+ <title>Le Mouv</title> |
|
| 30 |
+ <mp3>https://files.kawi.fr:8000/lemouv128</mp3> |
|
| 31 |
+ <shortname>lemouv</shortname> |
|
| 32 |
+ <icy>0</icy> |
|
| 33 |
+ </item> |
|
| 34 |
+ <item> |
|
| 35 |
+ <title>RFI Monde</title> |
|
| 36 |
+ <mp3>https://files.kawi.fr:8000/rfi</mp3> |
|
| 37 |
+ <shortname>rfi</shortname> |
|
| 38 |
+ <icy>0</icy> |
|
| 39 |
+ </item> |
|
| 40 |
+ <item> |
|
| 41 |
+ <title>Europe 1</title> |
|
| 42 |
+ <mp3>https://files.kawi.fr:8000/europe1</mp3> |
|
| 43 |
+ <shortname>europe1</shortname> |
|
| 44 |
+ <icy>1</icy> |
|
| 45 |
+ </item> |
|
| 46 |
+ <item> |
|
| 47 |
+ <title>Radio Classique</title> |
|
| 48 |
+ <mp3>https://files.kawi.fr:8000/radioclassique</mp3> |
|
| 49 |
+ <shortname>radio_classique</shortname> |
|
| 50 |
+ <icy>1</icy> |
|
| 51 |
+ </item> |
|
| 52 |
+ <item> |
|
| 53 |
+ <title>FIP</title> |
|
| 54 |
+ <mp3>https://files.kawi.fr:8000/fip128</mp3> |
|
| 55 |
+ <shortname>fipradio</shortname> |
|
| 56 |
+ <icy>0</icy> |
|
| 57 |
+ </item> |
|
| 58 |
+ <item> |
|
| 59 |
+ <title>Classic 21</title> |
|
| 60 |
+ <mp3>https://files.kawi.fr:8000/classic21</mp3> |
|
| 61 |
+ <shortname>classic21</shortname> |
|
| 62 |
+ <icy>0</icy> |
|
| 63 |
+ </item> |
|
| 64 |
+ <item> |
|
| 65 |
+ <title>Radio Nova</title> |
|
| 66 |
+ <mp3>https://files.kawi.fr:8000/nova128</mp3> |
|
| 67 |
+ <shortname>radio_nova</shortname> |
|
| 68 |
+ <icy>0</icy> |
|
| 69 |
+ </item> |
|
| 70 |
+ <item> |
|
| 71 |
+ <title>Suburbs of Goa (SomaFM)</title> |
|
| 72 |
+ <mp3>https://files.kawi.fr:8000/suburbsofgoa</mp3> |
|
| 73 |
+ <shortname>suburbsofgoa</shortname> |
|
| 74 |
+ <icy>1</icy> |
|
| 75 |
+ </item> |
|
| 76 |
+ <item> |
|
| 77 |
+ <title>Groove Salad (SomaFM)</title> |
|
| 78 |
+ <mp3>https://files.kawi.fr:8000/groovesalad</mp3> |
|
| 79 |
+ <shortname>groovesalad</shortname> |
|
| 80 |
+ <icy>1</icy> |
|
| 81 |
+ </item> |
|
| 82 |
+ <item> |
|
| 83 |
+ <title>Covers (SomaFM)</title> |
|
| 84 |
+ <mp3>https://files.kawi.fr:8000/covers</mp3> |
|
| 85 |
+ <shortname>covers</shortname> |
|
| 86 |
+ <icy>1</icy> |
|
| 87 |
+ </item> |
|
| 88 |
+ <item> |
|
| 89 |
+ <title>La Grosse Radio Rock</title> |
|
| 90 |
+ <mp3>https://files.kawi.fr:8000/lgrrock</mp3> |
|
| 91 |
+ <shortname>lgrrock</shortname> |
|
| 92 |
+ <icy>1</icy> |
|
| 93 |
+ </item> |
|
| 94 |
+ <item> |
|
| 95 |
+ <title>La Grosse Radio Metal</title> |
|
| 96 |
+ <mp3>https://files.kawi.fr:8000/lgrmetal</mp3> |
|
| 97 |
+ <shortname>lgrmetal</shortname> |
|
| 98 |
+ <icy>1</icy> |
|
| 99 |
+ </item> |
|
| 100 |
+ <item> |
|
| 101 |
+ <title>La Grosse Radio Reggae</title> |
|
| 102 |
+ <mp3>https://files.kawi.fr:8000/lgrreggae</mp3> |
|
| 103 |
+ <shortname>lgrreggae</shortname> |
|
| 104 |
+ <icy>1</icy> |
|
| 105 |
+ </item> |
|
| 106 |
+ <item> |
|
| 107 |
+ <title>Caribbean Reggae</title> |
|
| 108 |
+ <mp3>https://files.kawi.fr:8000/caribbean</mp3> |
|
| 109 |
+ <shortname>caribbean</shortname> |
|
| 110 |
+ <icy>1</icy> |
|
| 111 |
+ </item> |
|
| 112 |
+ <item> |
|
| 113 |
+ <title>Bassdrive</title> |
|
| 114 |
+ <mp3>https://files.kawi.fr:8000/bassdrive</mp3> |
|
| 115 |
+ <shortname>bassdrive</shortname> |
|
| 116 |
+ <icy>1</icy> |
|
| 117 |
+ </item> |
|
| 118 |
+ <item> |
|
| 119 |
+ <title>Stellar Attraction</title> |
|
| 120 |
+ <mp3>https://files.kawi.fr:8000/stellar</mp3> |
|
| 121 |
+ <shortname>stellar</shortname> |
|
| 122 |
+ <icy>1</icy> |
|
| 123 |
+ </item> |
|
| 124 |
+ <item> |
|
| 125 |
+ <title>BBC WS</title> |
|
| 126 |
+ <mp3>https://files.kawi.fr:8000/bbcws</mp3> |
|
| 127 |
+ <shortname>bbcws</shortname> |
|
| 128 |
+ <icy>1</icy> |
|
| 129 |
+ </item> |
|
| 130 |
+ <item> |
|
| 131 |
+ <title>Renegade Radio UK</title> |
|
| 132 |
+ <mp3>https://files.kawi.fr:8000/rruk</mp3> |
|
| 133 |
+ <shortname>rruk</shortname> |
|
| 134 |
+ <icy>1</icy> |
|
| 135 |
+ </item> |
|
| 136 |
+ <item> |
|
| 137 |
+ <title>Radio Flemme</title> |
|
| 138 |
+ <mp3>https://files.kawi.fr:8000/flemme</mp3> |
|
| 139 |
+ <shortname>flemme</shortname> |
|
| 140 |
+ <icy>0</icy> |
|
| 141 |
+ </item> |
|
| 142 |
+ <item> |
|
| 143 |
+ <title>Reggae World Crew</title> |
|
| 144 |
+ <mp3>https://files.kawi.fr:8000/reggaewc</mp3> |
|
| 145 |
+ <shortname>reggaewc</shortname> |
|
| 146 |
+ <icy>1</icy> |
|
| 147 |
+ </item> |
|
| 148 |
+ <item> |
|
| 149 |
+ <title>Trap.fm</title> |
|
| 150 |
+ <mp3>https://files.kawi.fr:8000/trapfm</mp3> |
|
| 151 |
+ <shortname>trapfm</shortname> |
|
| 152 |
+ <icy>1</icy> |
|
| 153 |
+ </item> |
|
| 154 |
+ <item> |
|
| 155 |
+ <title>Reggae World Music</title> |
|
| 156 |
+ <mp3>https://files.kawi.fr:8000/reggaeworldmusic</mp3> |
|
| 157 |
+ <shortname>reggaeworldmusic</shortname> |
|
| 158 |
+ <icy>1</icy> |
|
| 159 |
+ </item> |
|
| 160 |
+ </channel> |
|
| 161 |
+</channel_list> |
| ... | ... |
@@ -0,0 +1,161 @@ |
| 1 |
+<?xml version='1.0' encoding='UTF-8'?> |
|
| 2 |
+<channel_list> |
|
| 3 |
+ <channel> |
|
| 4 |
+ <item> |
|
| 5 |
+ <title>France Info</title> |
|
| 6 |
+ <mp3>http://direct.franceinfo.fr:80/live/franceinfo-lofi.mp3</mp3> |
|
| 7 |
+ <shortname>finfo</shortname> |
|
| 8 |
+ <icy>0</icy> |
|
| 9 |
+ </item> |
|
| 10 |
+ <item> |
|
| 11 |
+ <title>France Inter</title> |
|
| 12 |
+ <mp3>http://direct.franceinter.fr:80/live/franceinter-lofi.mp3</mp3> |
|
| 13 |
+ <shortname>finter</shortname> |
|
| 14 |
+ <icy>0</icy> |
|
| 15 |
+ </item> |
|
| 16 |
+ <item> |
|
| 17 |
+ <title>France Culture</title> |
|
| 18 |
+ <mp3>http://direct.franceculture.fr:80/live/franceculture-lofi.mp3</mp3> |
|
| 19 |
+ <shortname>fculture</shortname> |
|
| 20 |
+ <icy>0</icy> |
|
| 21 |
+ </item> |
|
| 22 |
+ <item> |
|
| 23 |
+ <title>France Musique</title> |
|
| 24 |
+ <mp3>http://direct.francemusique.fr:80/live/francemusique-midfi.mp3</mp3> |
|
| 25 |
+ <shortname>fmusique</shortname> |
|
| 26 |
+ <icy>0</icy> |
|
| 27 |
+ </item> |
|
| 28 |
+ <item> |
|
| 29 |
+ <title>Le Mouv</title> |
|
| 30 |
+ <mp3>http://direct.mouv.fr:80/live/mouv-midfi.mp3</mp3> |
|
| 31 |
+ <shortname>lemouv</shortname> |
|
| 32 |
+ <icy>0</icy> |
|
| 33 |
+ </item> |
|
| 34 |
+ <item> |
|
| 35 |
+ <title>RFI Monde</title> |
|
| 36 |
+ <mp3>http://live02.rfi.fr:80/rfimonde-64.mp3</mp3> |
|
| 37 |
+ <shortname>rfi</shortname> |
|
| 38 |
+ <icy>0</icy> |
|
| 39 |
+ </item> |
|
| 40 |
+ <item> |
|
| 41 |
+ <title>Europe 1</title> |
|
| 42 |
+ <mp3>http://e1-live-mp3-64.scdn.arkena.com:64/europe1.mp3</mp3> |
|
| 43 |
+ <shortname>europe1</shortname> |
|
| 44 |
+ <icy>1</icy> |
|
| 45 |
+ </item> |
|
| 46 |
+ <item> |
|
| 47 |
+ <title>Radio Classique</title> |
|
| 48 |
+ <mp3>http://radioclassique.ice.infomaniak.ch:80/radioclassique-high.mp3</mp3> |
|
| 49 |
+ <shortname>radio_classique</shortname> |
|
| 50 |
+ <icy>1</icy> |
|
| 51 |
+ </item> |
|
| 52 |
+ <item> |
|
| 53 |
+ <title>FIP</title> |
|
| 54 |
+ <mp3>http://direct.fipradio.fr:80/live/fip-midfi.mp3</mp3> |
|
| 55 |
+ <shortname>fipradio</shortname> |
|
| 56 |
+ <icy>0</icy> |
|
| 57 |
+ </item> |
|
| 58 |
+ <item> |
|
| 59 |
+ <title>Classic 21</title> |
|
| 60 |
+ <mp3>http://classic21.ice.rtbf.be:80/classic21-128.mp3</mp3> |
|
| 61 |
+ <shortname>classic21</shortname> |
|
| 62 |
+ <icy>0</icy> |
|
| 63 |
+ </item> |
|
| 64 |
+ <item> |
|
| 65 |
+ <title>Radio Nova</title> |
|
| 66 |
+ <mp3>http://novazz.ice.infomaniak.ch:80/novazz-128.mp3</mp3> |
|
| 67 |
+ <shortname>radio_nova</shortname> |
|
| 68 |
+ <icy>0</icy> |
|
| 69 |
+ </item> |
|
| 70 |
+ <item> |
|
| 71 |
+ <title>Suburbs of Goa (SomaFM)</title> |
|
| 72 |
+ <mp3>http://ice1.somafm.com:80/suburbsofgoa-128-mp3</mp3> |
|
| 73 |
+ <shortname>suburbsofgoa</shortname> |
|
| 74 |
+ <icy>1</icy> |
|
| 75 |
+ </item> |
|
| 76 |
+ <item> |
|
| 77 |
+ <title>Groove Salad (SomaFM)</title> |
|
| 78 |
+ <mp3>http://ice1.somafm.com:80/groovesalad-128-mp3</mp3> |
|
| 79 |
+ <shortname>groovesalad</shortname> |
|
| 80 |
+ <icy>1</icy> |
|
| 81 |
+ </item> |
|
| 82 |
+ <item> |
|
| 83 |
+ <title>Covers (SomaFM)</title> |
|
| 84 |
+ <mp3>http://ice1.somafm.com:80/covers-128-mp3</mp3> |
|
| 85 |
+ <shortname>covers</shortname> |
|
| 86 |
+ <icy>1</icy> |
|
| 87 |
+ </item> |
|
| 88 |
+ <item> |
|
| 89 |
+ <title>La Grosse Radio Rock</title> |
|
| 90 |
+ <mp3>http://hd.lagrosseradio.info:80/lagrosseradio-rock-064.mp3</mp3> |
|
| 91 |
+ <shortname>lgrrock</shortname> |
|
| 92 |
+ <icy>1</icy> |
|
| 93 |
+ </item> |
|
| 94 |
+ <item> |
|
| 95 |
+ <title>La Grosse Radio Metal</title> |
|
| 96 |
+ <mp3>http://hd.lagrosseradio.info:80/lagrosseradio-metal-064.mp3</mp3> |
|
| 97 |
+ <shortname>lgrmetal</shortname> |
|
| 98 |
+ <icy>1</icy> |
|
| 99 |
+ </item> |
|
| 100 |
+ <item> |
|
| 101 |
+ <title>La Grosse Radio Reggae</title> |
|
| 102 |
+ <mp3>http://hd.lagrosseradio.info:80/lagrosseradio-reggae-064.mp3</mp3> |
|
| 103 |
+ <shortname>lgrreggae</shortname> |
|
| 104 |
+ <icy>1</icy> |
|
| 105 |
+ </item> |
|
| 106 |
+ <item> |
|
| 107 |
+ <title>Caribbean Reggae</title> |
|
| 108 |
+ <mp3>http://strm112.1.fm:80/reggae_mobile_mp3</mp3> |
|
| 109 |
+ <shortname>caribbean</shortname> |
|
| 110 |
+ <icy>1</icy> |
|
| 111 |
+ </item> |
|
| 112 |
+ <item> |
|
| 113 |
+ <title>Bassdrive</title> |
|
| 114 |
+ <mp3>http://amsterdam2.shouthost.com.streams.bassdrive.com:8000/;stream.mp3</mp3> |
|
| 115 |
+ <shortname>bassdrive</shortname> |
|
| 116 |
+ <icy>1</icy> |
|
| 117 |
+ </item> |
|
| 118 |
+ <item> |
|
| 119 |
+ <title>Stellar Attraction</title> |
|
| 120 |
+ <mp3>http://77.68.36.137:8000/stream</mp3> |
|
| 121 |
+ <shortname>stellar</shortname> |
|
| 122 |
+ <icy>1</icy> |
|
| 123 |
+ </item> |
|
| 124 |
+ <item> |
|
| 125 |
+ <title>BBC WS</title> |
|
| 126 |
+ <mp3>http://bbcwssc.ic.llnwd.net:80/stream/bbcwssc_mp1_ws-eieuk</mp3> |
|
| 127 |
+ <shortname>bbcws</shortname> |
|
| 128 |
+ <icy>1</icy> |
|
| 129 |
+ </item> |
|
| 130 |
+ <item> |
|
| 131 |
+ <title>Renegade Radio UK</title> |
|
| 132 |
+ <mp3>http://69.30.213.131:80/stream</mp3> |
|
| 133 |
+ <shortname>rruk</shortname> |
|
| 134 |
+ <icy>1</icy> |
|
| 135 |
+ </item> |
|
| 136 |
+ <item> |
|
| 137 |
+ <title>Radio Flemme</title> |
|
| 138 |
+ <mp3>http://str45.streamakaci.com:8014/;895614762790501stream.nsv</mp3> |
|
| 139 |
+ <shortname>flemme</shortname> |
|
| 140 |
+ <icy>0</icy> |
|
| 141 |
+ </item> |
|
| 142 |
+ <item> |
|
| 143 |
+ <title>Reggae World Crew</title> |
|
| 144 |
+ <mp3>http://67.212.189.122:8042/;stream.nsv&type=mp3</mp3> |
|
| 145 |
+ <shortname>reggaewc</shortname> |
|
| 146 |
+ <icy>1</icy> |
|
| 147 |
+ </item> |
|
| 148 |
+ <item> |
|
| 149 |
+ <title>Trap.fm</title> |
|
| 150 |
+ <mp3>http://stream.trap.fm:6004/;stream.mp3</mp3> |
|
| 151 |
+ <shortname>trapfm</shortname> |
|
| 152 |
+ <icy>1</icy> |
|
| 153 |
+ </item> |
|
| 154 |
+ <item> |
|
| 155 |
+ <title>Reggae World Music</title> |
|
| 156 |
+ <mp3>http://s10.whooshclouds.net:8072/live?type=.mp3</mp3> |
|
| 157 |
+ <shortname>reggaeworldmusic</shortname> |
|
| 158 |
+ <icy>1</icy> |
|
| 159 |
+ </item> |
|
| 160 |
+ </channel> |
|
| 161 |
+</channel_list> |
| ... | ... |
@@ -0,0 +1,120 @@ |
| 1 |
+package com.yc.rss.radio; |
|
| 2 |
+ |
|
| 3 |
+import org.xmlpull.v1.XmlPullParser; |
|
| 4 |
+import org.xmlpull.v1.XmlPullParserException; |
|
| 5 |
+ |
|
| 6 |
+import java.io.IOException; |
|
| 7 |
+ |
|
| 8 |
+/** |
|
| 9 |
+ * Created by yc on 8/13/15. |
|
| 10 |
+ * https://developer.android.com/training/basics/network-ops/xml.html |
|
| 11 |
+ */ |
|
| 12 |
+/* |
|
| 13 |
+<channel> |
|
| 14 |
+ <title>France Info</title> |
|
| 15 |
+ <mp3>https://files.kawi.fr:8000/finfo64</mp3> |
|
| 16 |
+ <shortname>finfo</shortname> |
|
| 17 |
+ <icy>0</icy> |
|
| 18 |
+</channel> |
|
| 19 |
+ */ |
|
| 20 |
+public class Entry {
|
|
| 21 |
+ public final String title; |
|
| 22 |
+ public final String mp3; |
|
| 23 |
+ public final String shortname; |
|
| 24 |
+ public final String icy; |
|
| 25 |
+ public static final String ns = null; |
|
| 26 |
+ |
|
| 27 |
+ public Entry(String title, String mp3, String shortname, String icy) {
|
|
| 28 |
+ this.title = title; |
|
| 29 |
+ this.mp3 = mp3; |
|
| 30 |
+ this.shortname = shortname; |
|
| 31 |
+ this.icy = icy; |
|
| 32 |
+ } |
|
| 33 |
+ |
|
| 34 |
+ // Parses the contents of an entry. If it encounters a title, summary, or link tag, hands them off |
|
| 35 |
+ // to their respective "read" methods for processing. Otherwise, skips the tag. |
|
| 36 |
+ public static Entry readItem(XmlPullParser parser) throws XmlPullParserException, IOException {
|
|
| 37 |
+ parser.require(XmlPullParser.START_TAG, ns, "item"); |
|
| 38 |
+ String title = null; |
|
| 39 |
+ String mp3 = null; |
|
| 40 |
+ String shortname = null; |
|
| 41 |
+ String icy = null; |
|
| 42 |
+ while (parser.next() != XmlPullParser.END_TAG) {
|
|
| 43 |
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
|
|
| 44 |
+ continue; |
|
| 45 |
+ } |
|
| 46 |
+ String name = parser.getName(); |
|
| 47 |
+ if (name.equals("title")) {
|
|
| 48 |
+ title = readTitle(parser); |
|
| 49 |
+ } else if (name.equals("mp3")) {
|
|
| 50 |
+ mp3 = readMp3(parser); |
|
| 51 |
+ } else if (name.equals("shortname")) {
|
|
| 52 |
+ shortname = readShortname(parser); |
|
| 53 |
+ } else if (name.equals("icy")) {
|
|
| 54 |
+ icy = readIcy(parser); |
|
| 55 |
+ } else {
|
|
| 56 |
+ skip(parser); |
|
| 57 |
+ } |
|
| 58 |
+ } |
|
| 59 |
+ return new Entry(title, mp3, shortname, icy); |
|
| 60 |
+ } |
|
| 61 |
+ |
|
| 62 |
+ // Processes title tags in the feed. |
|
| 63 |
+ public static String readTitle(XmlPullParser parser) throws IOException, XmlPullParserException {
|
|
| 64 |
+ parser.require(XmlPullParser.START_TAG, ns, "title"); |
|
| 65 |
+ String title = readText(parser); |
|
| 66 |
+ parser.require(XmlPullParser.END_TAG, ns, "title"); |
|
| 67 |
+ return title; |
|
| 68 |
+ } |
|
| 69 |
+ |
|
| 70 |
+ // Processes category tags in the feed. |
|
| 71 |
+ public static String readMp3(XmlPullParser parser) throws IOException, XmlPullParserException {
|
|
| 72 |
+ parser.require(XmlPullParser.START_TAG, ns, "mp3"); |
|
| 73 |
+ String mp3 = readText(parser); |
|
| 74 |
+ parser.require(XmlPullParser.END_TAG, ns, "mp3"); |
|
| 75 |
+ return mp3; |
|
| 76 |
+ } |
|
| 77 |
+ |
|
| 78 |
+ // Processes link tags in the feed. |
|
| 79 |
+ public static String readShortname(XmlPullParser parser) throws IOException, XmlPullParserException {
|
|
| 80 |
+ parser.require(XmlPullParser.START_TAG, ns, "shortname"); |
|
| 81 |
+ String shortname = readText(parser); |
|
| 82 |
+ parser.require(XmlPullParser.END_TAG, ns, "shortname"); |
|
| 83 |
+ return shortname; |
|
| 84 |
+ } |
|
| 85 |
+ |
|
| 86 |
+ // Processes summary tags in the feed. |
|
| 87 |
+ public static String readIcy(XmlPullParser parser) throws IOException, XmlPullParserException {
|
|
| 88 |
+ parser.require(XmlPullParser.START_TAG, ns, "icy"); |
|
| 89 |
+ String icy = readText(parser); |
|
| 90 |
+ parser.require(XmlPullParser.END_TAG, ns, "icy"); |
|
| 91 |
+ return icy; |
|
| 92 |
+ } |
|
| 93 |
+ |
|
| 94 |
+ // For the tags title and summary, extracts their text values. |
|
| 95 |
+ public static String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
|
|
| 96 |
+ String result = ""; |
|
| 97 |
+ if (parser.next() == XmlPullParser.TEXT) {
|
|
| 98 |
+ result = parser.getText(); |
|
| 99 |
+ parser.nextTag(); |
|
| 100 |
+ } |
|
| 101 |
+ return result; |
|
| 102 |
+ } |
|
| 103 |
+ |
|
| 104 |
+ public static void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
|
|
| 105 |
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
|
|
| 106 |
+ throw new IllegalStateException(); |
|
| 107 |
+ } |
|
| 108 |
+ int depth = 1; |
|
| 109 |
+ while (depth != 0) {
|
|
| 110 |
+ switch (parser.next()) {
|
|
| 111 |
+ case XmlPullParser.END_TAG: |
|
| 112 |
+ depth--; |
|
| 113 |
+ break; |
|
| 114 |
+ case XmlPullParser.START_TAG: |
|
| 115 |
+ depth++; |
|
| 116 |
+ break; |
|
| 117 |
+ } |
|
| 118 |
+ } |
|
| 119 |
+ } |
|
| 120 |
+} |
| ... | ... |
@@ -0,0 +1,128 @@ |
| 1 |
+package com.yc.rss.radio; |
|
| 2 |
+ |
|
| 3 |
+import android.util.Log; |
|
| 4 |
+ |
|
| 5 |
+import org.xmlpull.v1.XmlPullParser; |
|
| 6 |
+import org.xmlpull.v1.XmlPullParserException; |
|
| 7 |
+ |
|
| 8 |
+import java.io.IOException; |
|
| 9 |
+ |
|
| 10 |
+/** |
|
| 11 |
+ * Created by yc on 8/13/15. |
|
| 12 |
+ * https://developer.android.com/training/basics/network-ops/xml.html |
|
| 13 |
+ */ |
|
| 14 |
+/* |
|
| 15 |
+<channel> |
|
| 16 |
+ <title>France Info</title> |
|
| 17 |
+ <mp3>https://files.kawi.fr:8000/finfo64</mp3> |
|
| 18 |
+ <shortname>finfo</shortname> |
|
| 19 |
+ <icy>0</icy> |
|
| 20 |
+</channel> |
|
| 21 |
+ */ |
|
| 22 |
+public class EntryTag {
|
|
| 23 |
+ public String title; |
|
| 24 |
+ public String shortname; |
|
| 25 |
+ public String track_title; |
|
| 26 |
+ public String track_artist; |
|
| 27 |
+ public String track_url; |
|
| 28 |
+ public String cover = null; |
|
| 29 |
+ public static final String ns = null; |
|
| 30 |
+ |
|
| 31 |
+ public EntryTag(String title, String shortname, String track_title, String track_artist, String track_url, String cover) {
|
|
| 32 |
+ this.title = title; |
|
| 33 |
+ this.shortname = shortname; |
|
| 34 |
+ this.track_title = track_title; |
|
| 35 |
+ this.track_artist = track_artist; |
|
| 36 |
+ this.track_url = track_url; |
|
| 37 |
+ this.cover = cover; |
|
| 38 |
+ } |
|
| 39 |
+ |
|
| 40 |
+ public static EntryTag readItem(XmlPullParser parser) throws XmlPullParserException, IOException {
|
|
| 41 |
+ parser.require(XmlPullParser.START_TAG, ns, "channel"); |
|
| 42 |
+ String title = null; |
|
| 43 |
+ String shortname = null; |
|
| 44 |
+ String track_title = null; |
|
| 45 |
+ String track_artist = null; |
|
| 46 |
+ String track_url = null; |
|
| 47 |
+ String cover = null; |
|
| 48 |
+ while (parser.next() != XmlPullParser.END_TAG) {
|
|
| 49 |
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
|
|
| 50 |
+ continue; |
|
| 51 |
+ } |
|
| 52 |
+ String name = parser.getName(); |
|
| 53 |
+ if (name.equals("title")) {
|
|
| 54 |
+ title = readTitle(parser); |
|
| 55 |
+ } else if (name.equals("shortname")) {
|
|
| 56 |
+ shortname = readShortname(parser); |
|
| 57 |
+ } else if (name.equals("track_title")) {
|
|
| 58 |
+ track_title = readTrackTitle(parser); |
|
| 59 |
+ } else if (name.equals("track_artist")) {
|
|
| 60 |
+ track_artist = readTrackArtist(parser); |
|
| 61 |
+ } else if (name.equals("track_url")) {
|
|
| 62 |
+ track_url = readTrackURL(parser); |
|
| 63 |
+ } else {
|
|
| 64 |
+ skip(parser); |
|
| 65 |
+ } |
|
| 66 |
+ } |
|
| 67 |
+ return new EntryTag(title, shortname, track_title, track_artist, track_url, cover); |
|
| 68 |
+ } |
|
| 69 |
+ |
|
| 70 |
+ public static String readTitle(XmlPullParser parser) throws IOException, XmlPullParserException {
|
|
| 71 |
+ parser.require(XmlPullParser.START_TAG, ns, "title"); |
|
| 72 |
+ String title = readText(parser); |
|
| 73 |
+ parser.require(XmlPullParser.END_TAG, ns, "title"); |
|
| 74 |
+ return title; |
|
| 75 |
+ } |
|
| 76 |
+ |
|
| 77 |
+ public static String readShortname(XmlPullParser parser) throws IOException, XmlPullParserException {
|
|
| 78 |
+ parser.require(XmlPullParser.START_TAG, ns, "shortname"); |
|
| 79 |
+ String shortname = readText(parser); |
|
| 80 |
+ parser.require(XmlPullParser.END_TAG, ns, "shortname"); |
|
| 81 |
+ return shortname; |
|
| 82 |
+ } |
|
| 83 |
+ |
|
| 84 |
+ public static String readTrackTitle(XmlPullParser parser) throws IOException, XmlPullParserException {
|
|
| 85 |
+ parser.require(XmlPullParser.START_TAG, ns, "track_title"); |
|
| 86 |
+ String icy = readText(parser); |
|
| 87 |
+ parser.require(XmlPullParser.END_TAG, ns, "track_title"); |
|
| 88 |
+ return icy; |
|
| 89 |
+ } |
|
| 90 |
+ public static String readTrackArtist(XmlPullParser parser) throws IOException, XmlPullParserException {
|
|
| 91 |
+ parser.require(XmlPullParser.START_TAG, ns, "track_artist"); |
|
| 92 |
+ String icy = readText(parser); |
|
| 93 |
+ parser.require(XmlPullParser.END_TAG, ns, "track_artist"); |
|
| 94 |
+ return icy; |
|
| 95 |
+ } |
|
| 96 |
+ public static String readTrackURL(XmlPullParser parser) throws IOException, XmlPullParserException {
|
|
| 97 |
+ parser.require(XmlPullParser.START_TAG, ns, "track_url"); |
|
| 98 |
+ String icy = readText(parser); |
|
| 99 |
+ parser.require(XmlPullParser.END_TAG, ns, "track_url"); |
|
| 100 |
+ return icy; |
|
| 101 |
+ } |
|
| 102 |
+ |
|
| 103 |
+ public static String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
|
|
| 104 |
+ String result = ""; |
|
| 105 |
+ if (parser.next() == XmlPullParser.TEXT) {
|
|
| 106 |
+ result = parser.getText(); |
|
| 107 |
+ parser.nextTag(); |
|
| 108 |
+ } |
|
| 109 |
+ return result; |
|
| 110 |
+ } |
|
| 111 |
+ |
|
| 112 |
+ public static void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
|
|
| 113 |
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
|
|
| 114 |
+ throw new IllegalStateException(); |
|
| 115 |
+ } |
|
| 116 |
+ int depth = 1; |
|
| 117 |
+ while (depth != 0) {
|
|
| 118 |
+ switch (parser.next()) {
|
|
| 119 |
+ case XmlPullParser.END_TAG: |
|
| 120 |
+ depth--; |
|
| 121 |
+ break; |
|
| 122 |
+ case XmlPullParser.START_TAG: |
|
| 123 |
+ depth++; |
|
| 124 |
+ break; |
|
| 125 |
+ } |
|
| 126 |
+ } |
|
| 127 |
+ } |
|
| 128 |
+} |
| ... | ... |
@@ -0,0 +1,598 @@ |
| 1 |
+package com.yc.rss.radio; |
|
| 2 |
+ |
|
| 3 |
+import android.app.Activity; |
|
| 4 |
+import android.app.IntentService; |
|
| 5 |
+import android.app.Notification; |
|
| 6 |
+import android.app.NotificationManager; |
|
| 7 |
+import android.app.PendingIntent; |
|
| 8 |
+import android.app.ProgressDialog; |
|
| 9 |
+import android.content.Intent; |
|
| 10 |
+import android.content.res.AssetManager; |
|
| 11 |
+import android.graphics.Bitmap; |
|
| 12 |
+import android.graphics.BitmapFactory; |
|
| 13 |
+import android.graphics.Canvas; |
|
| 14 |
+import android.graphics.Point; |
|
| 15 |
+import android.graphics.drawable.BitmapDrawable; |
|
| 16 |
+import android.media.AudioManager; |
|
| 17 |
+import android.media.MediaPlayer; |
|
| 18 |
+import android.os.AsyncTask; |
|
| 19 |
+import android.os.Build; |
|
| 20 |
+import android.os.Bundle; |
|
| 21 |
+import android.os.Environment; |
|
| 22 |
+import android.os.Handler; |
|
| 23 |
+import android.os.Message; |
|
| 24 |
+import android.support.v7.app.AppCompatActivity; |
|
| 25 |
+import android.support.v7.app.NotificationCompat; |
|
| 26 |
+import android.util.Log; |
|
| 27 |
+import android.view.Display; |
|
| 28 |
+import android.view.Menu; |
|
| 29 |
+import android.view.MenuItem; |
|
| 30 |
+import android.view.View; |
|
| 31 |
+import android.webkit.WebSettings; |
|
| 32 |
+import android.webkit.WebView; |
|
| 33 |
+import android.widget.ImageView; |
|
| 34 |
+import android.widget.ArrayAdapter; |
|
| 35 |
+import android.widget.ScrollView; |
|
| 36 |
+import android.widget.TextView; |
|
| 37 |
+import android.widget.Spinner; |
|
| 38 |
+import android.graphics.drawable.Drawable; |
|
| 39 |
+import android.widget.Toast; |
|
| 40 |
+ |
|
| 41 |
+import org.xmlpull.v1.XmlPullParserException; |
|
| 42 |
+ |
|
| 43 |
+import java.io.BufferedInputStream; |
|
| 44 |
+import java.io.ByteArrayInputStream; |
|
| 45 |
+import java.io.File; |
|
| 46 |
+import java.io.FileOutputStream; |
|
| 47 |
+import java.io.IOException; |
|
| 48 |
+import java.io.InputStream; |
|
| 49 |
+import java.io.OutputStream; |
|
| 50 |
+import java.net.HttpURLConnection; |
|
| 51 |
+import java.net.URL; |
|
| 52 |
+import java.net.URLConnection; |
|
| 53 |
+import java.nio.charset.StandardCharsets; |
|
| 54 |
+import java.util.ArrayList; |
|
| 55 |
+import java.util.HashSet; |
|
| 56 |
+import java.util.List; |
|
| 57 |
+ |
|
| 58 |
+public class MainActivity extends AppCompatActivity {
|
|
| 59 |
+ private ImageView mImageView; |
|
| 60 |
+ private ImageView mCoverView; |
|
| 61 |
+ private TextView mTextView; |
|
| 62 |
+ private TextView mTextViewArtist; |
|
| 63 |
+ private TextView mTextViewTitle; |
|
| 64 |
+ public static String articles; |
|
| 65 |
+ private Spinner spinArticle; |
|
| 66 |
+ private List<Entry> entries = null; |
|
| 67 |
+ public List<EntryTag> entries_tag = null; |
|
| 68 |
+ private int entries_sz = -1; |
|
| 69 |
+ public int entries_tag_sz = -1; |
|
| 70 |
+ private ProgressDialog pDialog; |
|
| 71 |
+ private DownloadFileFromURL mDownloadTags = null; |
|
| 72 |
+ private DownloadCoverFromURL mDownloadCover = null; |
|
| 73 |
+ private MediaPlayer mediaPlayer = null; |
|
| 74 |
+ private int current_pos = -1; |
|
| 75 |
+ private boolean initialState = true; |
|
| 76 |
+ private boolean initialNoTag = true; |
|
| 77 |
+ private static final int RADIO_NOTIFICATION=9999; |
|
| 78 |
+ public static final String ACTION_1 = "action_1"; |
|
| 79 |
+ public static final String ACTION_2 = "action_2"; |
|
| 80 |
+ public static final String ACTION_3 = "action_3"; |
|
| 81 |
+ public static final String ACTION_4 = "action_4"; |
|
| 82 |
+ |
|
| 83 |
+ private String old_title=""; |
|
| 84 |
+ private String old_artist=""; |
|
| 85 |
+ final Intent intentClick = null; |
|
| 86 |
+ |
|
| 87 |
+ public List<EntryTag> getTags() {
|
|
| 88 |
+ return entries_tag; |
|
| 89 |
+ } |
|
| 90 |
+ |
|
| 91 |
+ private Handler iSender = new Handler() {
|
|
| 92 |
+ @Override |
|
| 93 |
+ public void handleMessage(final Message msg) {
|
|
| 94 |
+ System.out.println("iSender");
|
|
| 95 |
+ mDownloadTags = (DownloadFileFromURL) new DownloadFileFromURL().execute(getString(R.string.tags_url)); |
|
| 96 |
+ iSender.sendEmptyMessageDelayed(0, 30*1000); |
|
| 97 |
+ } |
|
| 98 |
+ }; |
|
| 99 |
+ |
|
| 100 |
+ class DownloadFileFromURL extends AsyncTask<String, String, String> {
|
|
| 101 |
+ private String page_content; |
|
| 102 |
+ |
|
| 103 |
+ @Override |
|
| 104 |
+ protected void onPreExecute() {
|
|
| 105 |
+ super.onPreExecute(); |
|
| 106 |
+ System.out.println("Starting download");
|
|
| 107 |
+ /* |
|
| 108 |
+ pDialog = new ProgressDialog(MainActivity.this); |
|
| 109 |
+ pDialog.setMessage("Loading... Please wait...");
|
|
| 110 |
+ pDialog.setIndeterminate(false); |
|
| 111 |
+ pDialog.setCancelable(false); |
|
| 112 |
+ pDialog.show(); |
|
| 113 |
+ */ |
|
| 114 |
+ } |
|
| 115 |
+ |
|
| 116 |
+ @Override |
|
| 117 |
+ protected String doInBackground(String... f_url) {
|
|
| 118 |
+ int count; |
|
| 119 |
+ try {
|
|
| 120 |
+ URL url = new URL(f_url[0]); |
|
| 121 |
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection(); |
|
| 122 |
+ conn.setReadTimeout(10000 /* milliseconds */); |
|
| 123 |
+ conn.setConnectTimeout(15000 /* milliseconds */); |
|
| 124 |
+ conn.setRequestMethod("GET");
|
|
| 125 |
+ conn.setDoInput(true); |
|
| 126 |
+ conn.connect(); |
|
| 127 |
+ InputStream stream = conn.getInputStream(); |
|
| 128 |
+ StringBuilder page_content_builder = new StringBuilder(); |
|
| 129 |
+ byte data[] = new byte[65536]; |
|
| 130 |
+ while ((count = stream.read(data)) != -1) {
|
|
| 131 |
+ String str = new String(data, "UTF-8"); |
|
| 132 |
+ page_content_builder.append(str); |
|
| 133 |
+ } |
|
| 134 |
+ page_content = page_content_builder.toString(); |
|
| 135 |
+ } catch (Exception e) {
|
|
| 136 |
+ Log.e("Error: ", e.getMessage());
|
|
| 137 |
+ } |
|
| 138 |
+ return null; |
|
| 139 |
+ } |
|
| 140 |
+ |
|
| 141 |
+ @Override |
|
| 142 |
+ protected void onPostExecute(String file_url) {
|
|
| 143 |
+ System.out.println("Downloaded");
|
|
| 144 |
+ //pDialog.dismiss(); |
|
| 145 |
+ try {
|
|
| 146 |
+ TagsXmlParser tagsXmlParser = new TagsXmlParser(); |
|
| 147 |
+ InputStream stream = new ByteArrayInputStream(page_content.getBytes(StandardCharsets.UTF_8)); |
|
| 148 |
+ entries_tag = tagsXmlParser.parse(stream); |
|
| 149 |
+ entries_tag_sz = entries_tag.size(); |
|
| 150 |
+ } catch (IOException ignored) {
|
|
| 151 |
+ entries_tag = null; |
|
| 152 |
+ entries_tag_sz = -1; |
|
| 153 |
+ } catch (XmlPullParserException ignored) {
|
|
| 154 |
+ entries_tag = null; |
|
| 155 |
+ entries_tag_sz = -1; |
|
| 156 |
+ } |
|
| 157 |
+ if(true == initialNoTag ) {
|
|
| 158 |
+ initialNoTag = false; |
|
| 159 |
+ ToastThis(getString(R.string.tags_downloaded)); |
|
| 160 |
+ } |
|
| 161 |
+ ExtUpdate(); |
|
| 162 |
+ } |
|
| 163 |
+ } |
|
| 164 |
+ |
|
| 165 |
+ class DownloadCoverFromURL extends AsyncTask<String, String, String> {
|
|
| 166 |
+ private String page_content; |
|
| 167 |
+ private int pos; |
|
| 168 |
+ |
|
| 169 |
+ @Override |
|
| 170 |
+ protected void onPreExecute() {
|
|
| 171 |
+ super.onPreExecute(); |
|
| 172 |
+ System.out.println("Starting Cover download");
|
|
| 173 |
+ } |
|
| 174 |
+ |
|
| 175 |
+ @Override |
|
| 176 |
+ protected String doInBackground(String... f_url) {
|
|
| 177 |
+ int count; |
|
| 178 |
+ try {
|
|
| 179 |
+ pos = Integer.parseInt(f_url[0]); |
|
| 180 |
+ URL url = new URL(f_url[1]); |
|
| 181 |
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection(); |
|
| 182 |
+ conn.setReadTimeout(10000 /* milliseconds */); |
|
| 183 |
+ conn.setConnectTimeout(15000 /* milliseconds */); |
|
| 184 |
+ conn.setRequestMethod("GET");
|
|
| 185 |
+ conn.setDoInput(true); |
|
| 186 |
+ conn.connect(); |
|
| 187 |
+ InputStream stream = conn.getInputStream(); |
|
| 188 |
+ StringBuilder page_content_builder = new StringBuilder(); |
|
| 189 |
+ byte data[] = new byte[65536]; |
|
| 190 |
+ while ((count = stream.read(data)) != -1) {
|
|
| 191 |
+ String str = new String(data, "UTF-8"); |
|
| 192 |
+ page_content_builder.append(str); |
|
| 193 |
+ } |
|
| 194 |
+ page_content = page_content_builder.toString(); |
|
| 195 |
+ } catch (Exception e) {
|
|
| 196 |
+ Log.e("Error: ", e.getMessage());
|
|
| 197 |
+ } |
|
| 198 |
+ return null; |
|
| 199 |
+ } |
|
| 200 |
+ |
|
| 201 |
+ @Override |
|
| 202 |
+ protected void onPostExecute(String file_url) {
|
|
| 203 |
+ System.out.println("Cover Downloaded");
|
|
| 204 |
+ List<EntryTag> entries_tag = getTags(); |
|
| 205 |
+ EntryTag entry_tag = entries_tag.get(pos); |
|
| 206 |
+ entry_tag.cover = page_content; |
|
| 207 |
+ //ExtUpdate(); |
|
| 208 |
+ InputStream stream = new ByteArrayInputStream(page_content.getBytes(StandardCharsets.UTF_8)); |
|
| 209 |
+ //Bitmap bitmap = BitmapFactory.decodeStream(stream); |
|
| 210 |
+ //mCoverView.setImageBitmap(bitmap); |
|
| 211 |
+ Drawable d = Drawable.createFromStream(stream, null); |
|
| 212 |
+ mImageView.setImageDrawable(d); |
|
| 213 |
+ |
|
| 214 |
+ } |
|
| 215 |
+ } |
|
| 216 |
+ |
|
| 217 |
+ class Player extends AsyncTask<String, Void, Boolean> {
|
|
| 218 |
+ private ProgressDialog progress; |
|
| 219 |
+ |
|
| 220 |
+ @Override |
|
| 221 |
+ protected Boolean doInBackground(String... params) {
|
|
| 222 |
+ // TODO Auto-generated method stub |
|
| 223 |
+ Boolean prepared; |
|
| 224 |
+ try {
|
|
| 225 |
+ |
|
| 226 |
+ mediaPlayer.setDataSource(params[0]); |
|
| 227 |
+ |
|
| 228 |
+ mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
|
|
| 229 |
+ |
|
| 230 |
+ @Override |
|
| 231 |
+ public void onCompletion(MediaPlayer mp) {
|
|
| 232 |
+ // TODO Auto-generated method stub |
|
| 233 |
+// playPause=false; |
|
| 234 |
+// btn.setBackgroundResource(R.drawable.button_play); |
|
| 235 |
+ mediaPlayer.stop(); |
|
| 236 |
+ mediaPlayer.reset(); |
|
| 237 |
+ } |
|
| 238 |
+ }); |
|
| 239 |
+ mediaPlayer.prepare(); |
|
| 240 |
+ prepared = true; |
|
| 241 |
+ } catch (IllegalArgumentException e) {
|
|
| 242 |
+ // TODO Auto-generated catch block |
|
| 243 |
+ Log.d("IllegarArgument", e.getMessage());
|
|
| 244 |
+ prepared = false; |
|
| 245 |
+ e.printStackTrace(); |
|
| 246 |
+ } catch (SecurityException e) {
|
|
| 247 |
+ // TODO Auto-generated catch block |
|
| 248 |
+ prepared = false; |
|
| 249 |
+ e.printStackTrace(); |
|
| 250 |
+ } catch (IllegalStateException e) {
|
|
| 251 |
+ // TODO Auto-generated catch block |
|
| 252 |
+ prepared = false; |
|
| 253 |
+ e.printStackTrace(); |
|
| 254 |
+ } catch (IOException e) {
|
|
| 255 |
+ // TODO Auto-generated catch block |
|
| 256 |
+ prepared = false; |
|
| 257 |
+ e.printStackTrace(); |
|
| 258 |
+ } |
|
| 259 |
+ return prepared; |
|
| 260 |
+ } |
|
| 261 |
+ |
|
| 262 |
+ @Override |
|
| 263 |
+ protected void onPostExecute(Boolean result) {
|
|
| 264 |
+ // TODO Auto-generated method stub |
|
| 265 |
+ super.onPostExecute(result); |
|
| 266 |
+ if (progress.isShowing()) {
|
|
| 267 |
+ progress.cancel(); |
|
| 268 |
+ } |
|
| 269 |
+ Log.d("Prepared", "//" + result);
|
|
| 270 |
+ mediaPlayer.start(); |
|
| 271 |
+ } |
|
| 272 |
+ |
|
| 273 |
+ public Player() {
|
|
| 274 |
+ progress = new ProgressDialog(MainActivity.this); |
|
| 275 |
+ } |
|
| 276 |
+ |
|
| 277 |
+ @Override |
|
| 278 |
+ protected void onPreExecute() {
|
|
| 279 |
+ // TODO Auto-generated method stub |
|
| 280 |
+ super.onPreExecute(); |
|
| 281 |
+ this.progress.setMessage("Buffering...");
|
|
| 282 |
+ this.progress.show(); |
|
| 283 |
+ |
|
| 284 |
+ } |
|
| 285 |
+ } |
|
| 286 |
+ |
|
| 287 |
+ public void ToastThis(String message) {
|
|
| 288 |
+ Toast.makeText(this, |
|
| 289 |
+ message, |
|
| 290 |
+ Toast.LENGTH_SHORT).show(); |
|
| 291 |
+ } |
|
| 292 |
+ |
|
| 293 |
+ public static Bitmap drawableToBitmap (Drawable drawable) {
|
|
| 294 |
+ Bitmap bitmap = null; |
|
| 295 |
+ |
|
| 296 |
+ if (drawable instanceof BitmapDrawable) {
|
|
| 297 |
+ BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; |
|
| 298 |
+ if(bitmapDrawable.getBitmap() != null) {
|
|
| 299 |
+ return bitmapDrawable.getBitmap(); |
|
| 300 |
+ } |
|
| 301 |
+ } |
|
| 302 |
+ |
|
| 303 |
+ if(drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
|
|
| 304 |
+ bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel |
|
| 305 |
+ } else {
|
|
| 306 |
+ bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); |
|
| 307 |
+ } |
|
| 308 |
+ |
|
| 309 |
+ Canvas canvas = new Canvas(bitmap); |
|
| 310 |
+ drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); |
|
| 311 |
+ drawable.draw(canvas); |
|
| 312 |
+ return bitmap; |
|
| 313 |
+ } |
|
| 314 |
+ |
|
| 315 |
+ public void Notify(String shortname, String notificationTitle, String notificationMessage){
|
|
| 316 |
+ /*AssetManager am = getAssets(); |
|
| 317 |
+ try {
|
|
| 318 |
+ InputStream ims = am.open(shortname + ".jpg"); |
|
| 319 |
+ Drawable d = Drawable.createFromStream(ims, null); |
|
| 320 |
+ mNotifBuilder.setLargeIcon(drawableToBitmap(d)); |
|
| 321 |
+ } catch (IOException e) {
|
|
| 322 |
+ mNotifBuilder.setSmallIcon(R.drawable.ic_notification); |
|
| 323 |
+ } |
|
| 324 |
+ */ |
|
| 325 |
+ |
|
| 326 |
+ //mNotifBuilder.setSmallIcon(this.getResources().getIdentifier(shortname, "drawable", this.getPackageName())); |
|
| 327 |
+ |
|
| 328 |
+ /* |
|
| 329 |
+ Notification.Builder mBuilder = |
|
| 330 |
+ new Notification.Builder(this) |
|
| 331 |
+ .setSmallIcon(this.getResources().getIdentifier(shortname, "drawable", this.getPackageName())) |
|
| 332 |
+ .setContentTitle("CoderoMusicPlayer")
|
|
| 333 |
+ .setContentText("PLayer0!");
|
|
| 334 |
+ */ |
|
| 335 |
+ Notification.Builder mBuilder = new Notification.Builder(this); |
|
| 336 |
+ mBuilder.setSmallIcon(this.getResources().getIdentifier(shortname, "drawable", this.getPackageName())); |
|
| 337 |
+ if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {
|
|
| 338 |
+ mBuilder.setContentTitle(notificationTitle); |
|
| 339 |
+ mBuilder.setContentText(notificationMessage); |
|
| 340 |
+ } else {
|
|
| 341 |
+ mBuilder.setContentTitle(notificationTitle); |
|
| 342 |
+ mBuilder.setContentText(notificationMessage + "\n" + notificationTitle); |
|
| 343 |
+ mBuilder.setColor(this.getResources().getColor(android.R.color.white)); |
|
| 344 |
+ } |
|
| 345 |
+ |
|
| 346 |
+ mBuilder.setOngoing(true); |
|
| 347 |
+ |
|
| 348 |
+ Intent resultIntent = new Intent(this, MainActivity.class); |
|
| 349 |
+ resultIntent.setAction(Intent.ACTION_MAIN); |
|
| 350 |
+ resultIntent.addCategory(Intent.CATEGORY_LAUNCHER); |
|
| 351 |
+ |
|
| 352 |
+ PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, |
|
| 353 |
+ resultIntent, 0); |
|
| 354 |
+ |
|
| 355 |
+ mBuilder.setContentIntent(pendingIntent); |
|
| 356 |
+ NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); |
|
| 357 |
+ mNotificationManager.notify(9999, mBuilder.build()); |
|
| 358 |
+ } |
|
| 359 |
+ |
|
| 360 |
+ public void NotifyClear(){
|
|
| 361 |
+ NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); |
|
| 362 |
+ notificationManager.cancel(RADIO_NOTIFICATION); |
|
| 363 |
+ } |
|
| 364 |
+ |
|
| 365 |
+ @Override |
|
| 366 |
+ protected void onCreate(Bundle savedInstanceState) {
|
|
| 367 |
+ super.onCreate(savedInstanceState); |
|
| 368 |
+ |
|
| 369 |
+ iSender.sendEmptyMessage(0); |
|
| 370 |
+ mediaPlayer = new MediaPlayer(); |
|
| 371 |
+ mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); |
|
| 372 |
+ |
|
| 373 |
+ new Thread(new Runnable() {
|
|
| 374 |
+ @Override |
|
| 375 |
+ public void run() {
|
|
| 376 |
+ try {
|
|
| 377 |
+ Thread.sleep(5000); |
|
| 378 |
+ } catch (InterruptedException e) {
|
|
| 379 |
+ e.printStackTrace(); |
|
| 380 |
+ } |
|
| 381 |
+ runOnUiThread(new Runnable() {
|
|
| 382 |
+ @Override |
|
| 383 |
+ public void run() {
|
|
| 384 |
+ |
|
| 385 |
+ } |
|
| 386 |
+ }); |
|
| 387 |
+ } |
|
| 388 |
+ }).start(); |
|
| 389 |
+ |
|
| 390 |
+ setContentView(R.layout.activity_main); |
|
| 391 |
+ mImageView = (ImageView)findViewById(R.id.imageView); |
|
| 392 |
+ mCoverView = (ImageView)findViewById(R.id.imageViewTrack); |
|
| 393 |
+ mTextView = (TextView) findViewById(R.id.textView); |
|
| 394 |
+ mTextViewArtist = (TextView) findViewById(R.id.textViewArtist); |
|
| 395 |
+ mTextViewTitle = (TextView) findViewById(R.id.textViewTitle); |
|
| 396 |
+ spinArticle = (Spinner) findViewById(R.id.spinner_article); |
|
| 397 |
+ addListenerOnSpinnerItemSelection(); |
|
| 398 |
+ } |
|
| 399 |
+ |
|
| 400 |
+ public void ExtUpdate() {
|
|
| 401 |
+ int pos = spinArticle.getSelectedItemPosition(); |
|
| 402 |
+ if( current_pos != pos ) {
|
|
| 403 |
+ NotifyClear(); |
|
| 404 |
+ if (mediaPlayer.isPlaying()) {
|
|
| 405 |
+ mediaPlayer.stop(); |
|
| 406 |
+ } |
|
| 407 |
+ } |
|
| 408 |
+ |
|
| 409 |
+ try {
|
|
| 410 |
+ if( -1 == entries_sz ) {
|
|
| 411 |
+ FeedParser(); |
|
| 412 |
+ } |
|
| 413 |
+ AssetManager am = getAssets(); |
|
| 414 |
+ String resourcefilename=entries.get(pos).shortname; |
|
| 415 |
+ //InputStream ims = am.open(resourcefilename+".jpg"); |
|
| 416 |
+ InputStream ims = am.open(resourcefilename+".png"); |
|
| 417 |
+ Drawable d = Drawable.createFromStream(ims, null); |
|
| 418 |
+ mImageView.setImageDrawable(d); |
|
| 419 |
+ if(null== entries_tag) {
|
|
| 420 |
+ mTextView.setText(entries.get(pos).title); |
|
| 421 |
+ mCoverView.setImageDrawable(d); |
|
| 422 |
+ } else {
|
|
| 423 |
+ mTextView.setText(entries_tag.get(pos).title); |
|
| 424 |
+ //mTextViewTitle.setText(entries_tag.get(pos).track_title); |
|
| 425 |
+ if(! entries_tag.get(pos).track_title.equals("An Error Occured")) {
|
|
| 426 |
+ mTextViewTitle.setText(entries_tag.get(pos).track_title); |
|
| 427 |
+ } else {
|
|
| 428 |
+ mTextViewTitle.setText("");
|
|
| 429 |
+ } |
|
| 430 |
+ //mTextViewArtist.setText(entries_tag.get(pos).track_artist); |
|
| 431 |
+ if(! entries_tag.get(pos).track_artist.equals("An Error Occured")) {
|
|
| 432 |
+ mTextViewArtist.setText(entries_tag.get(pos).track_artist); |
|
| 433 |
+ } else {
|
|
| 434 |
+ mTextViewArtist.setText("");
|
|
| 435 |
+ } |
|
| 436 |
+ if( (!old_artist.equals(mTextViewArtist.getText().toString())) || |
|
| 437 |
+ (!old_title.equals(mTextViewTitle.getText().toString())) ) {
|
|
| 438 |
+ Notify(entries.get(pos).shortname, |
|
| 439 |
+ mTextViewArtist.getText().toString(), |
|
| 440 |
+ mTextViewTitle.getText().toString()); |
|
| 441 |
+ old_artist = mTextViewArtist.getText().toString(); |
|
| 442 |
+ old_title = mTextViewTitle.getText().toString(); |
|
| 443 |
+ } |
|
| 444 |
+ /* |
|
| 445 |
+ if(! entries_tag.get(pos).track_url.equals("")) {
|
|
| 446 |
+ System.out.println(entries_tag.get(pos).track_url); |
|
| 447 |
+ if (null != entries_tag.get(pos).cover) {
|
|
| 448 |
+ InputStream stream = new ByteArrayInputStream(entries_tag.get(pos).cover.getBytes(StandardCharsets.UTF_8)); |
|
| 449 |
+ d = Drawable.createFromStream(stream, null); |
|
| 450 |
+ mCoverView.setImageDrawable(d); |
|
| 451 |
+ } else {
|
|
| 452 |
+ mDownloadCover = (DownloadCoverFromURL) new DownloadCoverFromURL().execute(Integer.toString(pos),entries_tag.get(pos).track_url); |
|
| 453 |
+ } |
|
| 454 |
+ } else {
|
|
| 455 |
+ mCoverView.setImageDrawable(d); |
|
| 456 |
+ }*/ |
|
| 457 |
+ mCoverView.setImageDrawable(d); |
|
| 458 |
+ } |
|
| 459 |
+ } catch (IOException e) {
|
|
| 460 |
+ e.printStackTrace(); |
|
| 461 |
+ } |
|
| 462 |
+ |
|
| 463 |
+ Log.d("ExtUpdate DEBUG:", "Start Playing");
|
|
| 464 |
+ if( current_pos != pos ) {
|
|
| 465 |
+ current_pos = pos; |
|
| 466 |
+ mediaPlayer = new MediaPlayer(); |
|
| 467 |
+ new Player().execute(entries.get(pos).mp3); |
|
| 468 |
+ if( entries_tag != null ) {
|
|
| 469 |
+ if (entries_tag.get(pos) != null) {
|
|
| 470 |
+ if ((null != entries_tag.get(pos).track_artist) && |
|
| 471 |
+ (null != entries_tag.get(pos).track_artist)) {
|
|
| 472 |
+ Notify(entries.get(pos).shortname, entries_tag.get(pos).track_artist, entries_tag.get(pos).track_title); |
|
| 473 |
+ } else {
|
|
| 474 |
+ Notify(entries.get(pos).shortname, entries.get(pos).title, getString(R.string.tags_not_found)); |
|
| 475 |
+ } |
|
| 476 |
+ } else {
|
|
| 477 |
+ Notify(entries.get(pos).shortname, entries.get(pos).title, getString(R.string.tags_not_found)); |
|
| 478 |
+ } |
|
| 479 |
+ } else {
|
|
| 480 |
+ Notify(entries.get(pos).shortname, entries.get(pos).title, getString(R.string.tags_not_dl)); |
|
| 481 |
+ } |
|
| 482 |
+ } |
|
| 483 |
+ } |
|
| 484 |
+ |
|
| 485 |
+ public void addListenerOnSpinnerItemSelection(){
|
|
| 486 |
+ spinArticle.setOnItemSelectedListener(new SpinnerActivity()); |
|
| 487 |
+ } |
|
| 488 |
+ |
|
| 489 |
+ @Override |
|
| 490 |
+ public boolean onSupportNavigateUp(){
|
|
| 491 |
+ finish(); |
|
| 492 |
+ return true; |
|
| 493 |
+ } |
|
| 494 |
+ |
|
| 495 |
+ public boolean updateListView() {
|
|
| 496 |
+ boolean ret = false; |
|
| 497 |
+ String [] items1 = null; |
|
| 498 |
+ ArrayList al = new ArrayList<String>(); |
|
| 499 |
+ try {
|
|
| 500 |
+ items1 = doDropDown(); |
|
| 501 |
+ } catch( Exception e ) {
|
|
| 502 |
+ return ret; |
|
| 503 |
+ } |
|
| 504 |
+ |
|
| 505 |
+ ArrayAdapter<String> adapter1 = new ArrayAdapter<String>(this, |
|
| 506 |
+ android.R.layout.simple_spinner_item, items1); |
|
| 507 |
+ adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); |
|
| 508 |
+ spinArticle.setAdapter(adapter1); |
|
| 509 |
+ adapter1.notifyDataSetChanged(); |
|
| 510 |
+ return true; |
|
| 511 |
+ } |
|
| 512 |
+ |
|
| 513 |
+ @Override |
|
| 514 |
+ public boolean onCreateOptionsMenu(Menu menu) {
|
|
| 515 |
+ // Inflate the menu; this adds items to the action bar if it is present. |
|
| 516 |
+ getMenuInflater().inflate(R.menu.menu_main, menu); |
|
| 517 |
+ MenuItem menuItemDateRefresh = menu.findItem(R.id.last_refresh_date); |
|
| 518 |
+ menuItemDateRefresh.setTitle(getString(R.string.version)); |
|
| 519 |
+ return true; |
|
| 520 |
+ } |
|
| 521 |
+ |
|
| 522 |
+ |
|
| 523 |
+ @Override |
|
| 524 |
+ public boolean onOptionsItemSelected(MenuItem item) {
|
|
| 525 |
+ // Handle action bar item clicks here. The action bar will |
|
| 526 |
+ // automatically handle clicks on the Home/Up button, so long |
|
| 527 |
+ // as you specify a parent activity in AndroidManifest.xml. |
|
| 528 |
+ int id = item.getItemId(); |
|
| 529 |
+ if (id == R.id.action_exit) {
|
|
| 530 |
+ NotifyClear(); |
|
| 531 |
+ if (mediaPlayer.isPlaying()) {
|
|
| 532 |
+ mediaPlayer.stop(); |
|
| 533 |
+ } |
|
| 534 |
+ finish(); |
|
| 535 |
+ System.exit(0); |
|
| 536 |
+ return true; |
|
| 537 |
+ } |
|
| 538 |
+ |
|
| 539 |
+ return super.onOptionsItemSelected(item); |
|
| 540 |
+ } |
|
| 541 |
+ |
|
| 542 |
+ private void FeedParser() {
|
|
| 543 |
+ RadioXmlParser radioXmlParser = new RadioXmlParser(); |
|
| 544 |
+ InputStream stream = null; |
|
| 545 |
+ AssetManager am = getAssets(); |
|
| 546 |
+ try {
|
|
| 547 |
+ stream = am.open("radio.xml");
|
|
| 548 |
+ try {
|
|
| 549 |
+ entries = radioXmlParser.parse(stream); |
|
| 550 |
+ entries_sz = entries.size(); |
|
| 551 |
+ updateListView(); |
|
| 552 |
+ invalidateOptionsMenu(); |
|
| 553 |
+ if( initialState == true ) {
|
|
| 554 |
+ initialState = false; |
|
| 555 |
+ spinArticle.setSelection(0, true); |
|
| 556 |
+ } |
|
| 557 |
+ } catch (IOException ignored) {
|
|
| 558 |
+ entries = null; |
|
| 559 |
+ entries_sz = -1; |
|
| 560 |
+ } catch (XmlPullParserException ignored) {
|
|
| 561 |
+ entries = null; |
|
| 562 |
+ entries_sz = -1; |
|
| 563 |
+ } |
|
| 564 |
+ if (null != stream) {
|
|
| 565 |
+ try {
|
|
| 566 |
+ stream.close(); |
|
| 567 |
+ } catch (IOException e) {
|
|
| 568 |
+ } |
|
| 569 |
+ } |
|
| 570 |
+ |
|
| 571 |
+ } catch (IOException e) {
|
|
| 572 |
+ e.printStackTrace(); |
|
| 573 |
+ entries = null; |
|
| 574 |
+ entries_sz = -1; |
|
| 575 |
+ } |
|
| 576 |
+ } |
|
| 577 |
+ |
|
| 578 |
+ /** Feed 2 Article list for Spinner */ |
|
| 579 |
+ private String[] doDropDown() throws IOException {
|
|
| 580 |
+ String[] strings; |
|
| 581 |
+ if( -1 == entries_sz ) {
|
|
| 582 |
+ FeedParser(); |
|
| 583 |
+ } |
|
| 584 |
+ |
|
| 585 |
+ HashSet<String> hs = new HashSet<String>(); |
|
| 586 |
+ List<String> mStrings = new ArrayList<String>(); |
|
| 587 |
+ int i = 0; |
|
| 588 |
+ for( i = 0; i < entries_sz; i ++ ) |
|
| 589 |
+ {
|
|
| 590 |
+ Entry temp = entries.get(i); |
|
| 591 |
+ mStrings.add(i,temp.title); |
|
| 592 |
+ } |
|
| 593 |
+ mStrings.addAll(hs); |
|
| 594 |
+ strings = new String[mStrings.size()]; |
|
| 595 |
+ strings = mStrings.toArray(strings); |
|
| 596 |
+ return strings; |
|
| 597 |
+ } |
|
| 598 |
+} |
| ... | ... |
@@ -0,0 +1,70 @@ |
| 1 |
+package com.yc.rss.radio; |
|
| 2 |
+ |
|
| 3 |
+import android.util.Xml; |
|
| 4 |
+ |
|
| 5 |
+import org.xmlpull.v1.XmlPullParser; |
|
| 6 |
+import org.xmlpull.v1.XmlPullParserException; |
|
| 7 |
+ |
|
| 8 |
+import java.io.IOException; |
|
| 9 |
+import java.io.InputStream; |
|
| 10 |
+import java.util.ArrayList; |
|
| 11 |
+import java.util.List; |
|
| 12 |
+ |
|
| 13 |
+public class RadioXmlParser {
|
|
| 14 |
+ // We don't use namespaces |
|
| 15 |
+ private static final String ns = null; |
|
| 16 |
+ |
|
| 17 |
+ public List parse(InputStream in) throws XmlPullParserException, IOException {
|
|
| 18 |
+ try {
|
|
| 19 |
+ XmlPullParser parser = Xml.newPullParser(); |
|
| 20 |
+ parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); |
|
| 21 |
+ parser.setInput(in, null); |
|
| 22 |
+ parser.nextTag(); |
|
| 23 |
+ return readFeed(parser); |
|
| 24 |
+ } finally {
|
|
| 25 |
+ in.close(); |
|
| 26 |
+ } |
|
| 27 |
+ } |
|
| 28 |
+ |
|
| 29 |
+ private List readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {
|
|
| 30 |
+ List entries = new ArrayList(); |
|
| 31 |
+ Entry entry = new Entry("a","b","c","d");
|
|
| 32 |
+ |
|
| 33 |
+ parser.require(XmlPullParser.START_TAG, ns, "channel_list"); |
|
| 34 |
+ while (parser.next() != XmlPullParser.END_TAG) {
|
|
| 35 |
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
|
|
| 36 |
+ continue; |
|
| 37 |
+ } |
|
| 38 |
+ String name = parser.getName(); |
|
| 39 |
+ // Starts by looking for the item tag |
|
| 40 |
+ if (name.equals("channel")) {
|
|
| 41 |
+ |
|
| 42 |
+ //entries.add(entry.readEntry(parser)); |
|
| 43 |
+ entries = readFeedChannel(parser); |
|
| 44 |
+ } else {
|
|
| 45 |
+ entry.skip(parser); |
|
| 46 |
+ } |
|
| 47 |
+ } |
|
| 48 |
+ return entries; |
|
| 49 |
+ } |
|
| 50 |
+ private List readFeedChannel(XmlPullParser parser) throws XmlPullParserException, IOException {
|
|
| 51 |
+ List entries = new ArrayList(); |
|
| 52 |
+ Entry entry = new Entry("a","b","c","d");
|
|
| 53 |
+ |
|
| 54 |
+ parser.require(XmlPullParser.START_TAG, ns, "channel"); |
|
| 55 |
+ while (parser.next() != XmlPullParser.END_TAG) {
|
|
| 56 |
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
|
|
| 57 |
+ continue; |
|
| 58 |
+ } |
|
| 59 |
+ String name = parser.getName(); |
|
| 60 |
+ // Starts by looking for the item tag |
|
| 61 |
+ if (name.equals("item")) {
|
|
| 62 |
+ |
|
| 63 |
+ entries.add(entry.readItem(parser)); |
|
| 64 |
+ } else {
|
|
| 65 |
+ entry.skip(parser); |
|
| 66 |
+ } |
|
| 67 |
+ } |
|
| 68 |
+ return entries; |
|
| 69 |
+ } |
|
| 70 |
+} |
| ... | ... |
@@ -0,0 +1,21 @@ |
| 1 |
+package com.yc.rss.radio; |
|
| 2 |
+ |
|
| 3 |
+import android.app.Activity; |
|
| 4 |
+import android.view.View; |
|
| 5 |
+import android.widget.AdapterView; |
|
| 6 |
+ |
|
| 7 |
+ |
|
| 8 |
+/** |
|
| 9 |
+ * Created by cawidrone on 8/17/15. |
|
| 10 |
+ */ |
|
| 11 |
+public class SpinnerActivity extends Activity implements AdapterView.OnItemSelectedListener {
|
|
| 12 |
+ public void onItemSelected(AdapterView<?> parent, View view, |
|
| 13 |
+ int pos, long id) {
|
|
| 14 |
+ MainActivity mainActivity = (MainActivity)parent.getContext(); |
|
| 15 |
+ mainActivity.ExtUpdate(); |
|
| 16 |
+ } |
|
| 17 |
+ |
|
| 18 |
+ public void onNothingSelected(AdapterView<?> parent) {
|
|
| 19 |
+ // Another interface callback |
|
| 20 |
+ } |
|
| 21 |
+} |
| ... | ... |
@@ -0,0 +1,47 @@ |
| 1 |
+package com.yc.rss.radio; |
|
| 2 |
+ |
|
| 3 |
+import android.util.Xml; |
|
| 4 |
+ |
|
| 5 |
+import org.xmlpull.v1.XmlPullParser; |
|
| 6 |
+import org.xmlpull.v1.XmlPullParserException; |
|
| 7 |
+ |
|
| 8 |
+import java.io.IOException; |
|
| 9 |
+import java.io.InputStream; |
|
| 10 |
+import java.util.ArrayList; |
|
| 11 |
+import java.util.List; |
|
| 12 |
+ |
|
| 13 |
+public class TagsXmlParser {
|
|
| 14 |
+ // We don't use namespaces |
|
| 15 |
+ private static final String ns = null; |
|
| 16 |
+ |
|
| 17 |
+ public List parse(InputStream in) throws XmlPullParserException, IOException {
|
|
| 18 |
+ try {
|
|
| 19 |
+ XmlPullParser parser = Xml.newPullParser(); |
|
| 20 |
+ parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); |
|
| 21 |
+ parser.setInput(in, null); |
|
| 22 |
+ parser.nextTag(); |
|
| 23 |
+ return readFeed(parser); |
|
| 24 |
+ } finally {
|
|
| 25 |
+ in.close(); |
|
| 26 |
+ } |
|
| 27 |
+ } |
|
| 28 |
+ |
|
| 29 |
+ private List readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {
|
|
| 30 |
+ List entries = new ArrayList(); |
|
| 31 |
+ EntryTag entry = new EntryTag("a","b","c","d","e","f");
|
|
| 32 |
+ |
|
| 33 |
+ parser.require(XmlPullParser.START_TAG, ns, "channel_list"); |
|
| 34 |
+ while (parser.next() != XmlPullParser.END_TAG) {
|
|
| 35 |
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
|
|
| 36 |
+ continue; |
|
| 37 |
+ } |
|
| 38 |
+ String name = parser.getName(); |
|
| 39 |
+ if (name.equals("channel")) {
|
|
| 40 |
+ entries.add(entry.readItem(parser)); |
|
| 41 |
+ } else {
|
|
| 42 |
+ entry.skip(parser); |
|
| 43 |
+ } |
|
| 44 |
+ } |
|
| 45 |
+ return entries; |
|
| 46 |
+ } |
|
| 47 |
+} |
| ... | ... |
@@ -0,0 +1,19 @@ |
| 1 |
+#!/bin/bash |
|
| 2 |
+ |
|
| 3 |
+FILENAME=$1 |
|
| 4 |
+ |
|
| 5 |
+if [ -z $1 ] |
|
| 6 |
+then |
|
| 7 |
+ echo "$(basename $0) filename.png" |
|
| 8 |
+ exit 1 |
|
| 9 |
+fi |
|
| 10 |
+ |
|
| 11 |
+cp $FILENAME drawable/ic_launcher.png |
|
| 12 |
+cp $FILENAME mipmap-mdpi/ic_launcher.png |
|
| 13 |
+cp $FILENAME mipmap-hdpi/ic_launcher.png |
|
| 14 |
+cp $FILENAME mipmap-xhdpi/ic_launcher.png; |
|
| 15 |
+cp $FILENAME mipmap-xxhdpi/ic_launcher.png |
|
| 16 |
+mogrify -resize 72x72 mipmap-mdpi/ic_launcher.png |
|
| 17 |
+mogrify -resize 72x72 mipmap-hdpi/ic_launcher.png |
|
| 18 |
+mogrify -resize 96x96 mipmap-xhdpi/ic_launcher.png |
|
| 19 |
+mogrify -resize 144x144 mipmap-xxhdpi/ic_launcher.png |
| ... | ... |
@@ -0,0 +1,65 @@ |
| 1 |
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
|
| 2 |
+ android:orientation="vertical" |
|
| 3 |
+ android:layout_width="match_parent" |
|
| 4 |
+ android:layout_height="match_parent"> |
|
| 5 |
+ <Spinner |
|
| 6 |
+ android:id="@+id/spinner_article" |
|
| 7 |
+ android:layout_width="match_parent" |
|
| 8 |
+ android:layout_height="50dp" |
|
| 9 |
+ android:entries="@array/article_arrays" |
|
| 10 |
+ android:prompt="@string/article_prompt" |
|
| 11 |
+ android:background="#cdcdcd" /> |
|
| 12 |
+ |
|
| 13 |
+ <TextView |
|
| 14 |
+ android:layout_width="fill_parent" |
|
| 15 |
+ android:layout_height="50dp" |
|
| 16 |
+ android:id="@+id/textView" |
|
| 17 |
+ android:layout_centerHorizontal="true" |
|
| 18 |
+ android:layout_gravity="center" |
|
| 19 |
+ android:textAlignment="center" |
|
| 20 |
+ android:textColor="#000000" |
|
| 21 |
+ android:textStyle="italic" |
|
| 22 |
+ android:textSize="38dp" /> |
|
| 23 |
+ |
|
| 24 |
+ <TextView |
|
| 25 |
+ android:layout_width="fill_parent" |
|
| 26 |
+ android:layout_height="75dp" |
|
| 27 |
+ android:id="@+id/textViewArtist" |
|
| 28 |
+ android:layout_centerHorizontal="true" |
|
| 29 |
+ android:layout_gravity="center" |
|
| 30 |
+ android:textAlignment="center" |
|
| 31 |
+ android:textColor="#000000" |
|
| 32 |
+ android:textStyle="normal|bold" |
|
| 33 |
+ android:textSize="32dp" /> |
|
| 34 |
+ |
|
| 35 |
+ <TextView |
|
| 36 |
+ android:layout_width="fill_parent" |
|
| 37 |
+ android:layout_height="120dp" |
|
| 38 |
+ android:id="@+id/textViewTitle" |
|
| 39 |
+ android:layout_centerHorizontal="true" |
|
| 40 |
+ android:layout_gravity="center" |
|
| 41 |
+ android:capitalize="words" |
|
| 42 |
+ android:enabled="false" |
|
| 43 |
+ android:textAlignment="center" |
|
| 44 |
+ android:textColor="#000000" |
|
| 45 |
+ android:textSize="24dp" |
|
| 46 |
+ android:textStyle="normal" /> |
|
| 47 |
+ |
|
| 48 |
+ <ImageView |
|
| 49 |
+ android:layout_width="144dp" |
|
| 50 |
+ android:layout_height="144dp" |
|
| 51 |
+ android:id="@+id/imageViewTrack" |
|
| 52 |
+ android:layout_centerHorizontal="true" |
|
| 53 |
+ android:layout_centerVertical="true" |
|
| 54 |
+ android:background="@drawable/ic_launcher_big" |
|
| 55 |
+ android:layout_gravity="center" /> |
|
| 56 |
+ |
|
| 57 |
+ <ImageView |
|
| 58 |
+ android:layout_width="96dp" |
|
| 59 |
+ android:layout_height="96dp" |
|
| 60 |
+ android:id="@+id/imageView" |
|
| 61 |
+ android:layout_alignParentBottom="true" |
|
| 62 |
+ android:background="@drawable/ic_launcher" |
|
| 63 |
+ android:layout_gravity="top" |
|
| 64 |
+ android:visibility="invisible" /> |
|
| 65 |
+</LinearLayout> |
| ... | ... |
@@ -0,0 +1,12 @@ |
| 1 |
+<menu xmlns:android="http://schemas.android.com/apk/res/android" |
|
| 2 |
+ xmlns:app="http://schemas.android.com/apk/res-auto" |
|
| 3 |
+ xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity"> |
|
| 4 |
+ |
|
| 5 |
+ <item android:id="@+id/last_refresh_date" |
|
| 6 |
+ android:title="@string/action_last_refresh_date" |
|
| 7 |
+ android:orderInCategory="100" app:showAsAction="always|withText" /> |
|
| 8 |
+ |
|
| 9 |
+ <item android:id="@+id/action_exit" |
|
| 10 |
+ android:title="@string/action_exit" |
|
| 11 |
+ android:orderInCategory="100" app:showAsAction="never" /> |
|
| 12 |
+</menu> |
| ... | ... |
@@ -0,0 +1,6 @@ |
| 1 |
+<resources> |
|
| 2 |
+ <!-- Example customization of dimensions originally defined in res/values/dimens.xml |
|
| 3 |
+ (such as screen margins) for screens with more than 820dp of available width. This |
|
| 4 |
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). --> |
|
| 5 |
+ <dimen name="activity_horizontal_margin">0dp</dimen> |
|
| 6 |
+</resources> |
| ... | ... |
@@ -0,0 +1,7 @@ |
| 1 |
+<resources> |
|
| 2 |
+ <!-- Default screen margins, per the Android Design guidelines. --> |
|
| 3 |
+ <!-- <dimen name="activity_horizontal_margin">16dp</dimen> |
|
| 4 |
+ <dimen name="activity_vertical_margin">16dp</dimen> --> |
|
| 5 |
+ <dimen name="activity_horizontal_margin">0dp</dimen> |
|
| 6 |
+ <dimen name="activity_vertical_margin">0dp</dimen> |
|
| 7 |
+</resources> |
| ... | ... |
@@ -0,0 +1,16 @@ |
| 1 |
+<resources> |
|
| 2 |
+ <string name="app_name">Radio</string> |
|
| 3 |
+ <string name="version">2017-06-13</string> |
|
| 4 |
+ <string name="hello_world">Radio Player</string> |
|
| 5 |
+ <string name="action_exit">Exit</string> |
|
| 6 |
+ <string name="action_last_refresh_date"></string> |
|
| 7 |
+ <!-- <string name="tags_url">https://files.kawi.fr/radio/tags.xml</string> --> |
|
| 8 |
+ <string name="tags_url">https://kawi.fr/radio/tags.xml</string> |
|
| 9 |
+ <string name="article_prompt">Choose an article</string> |
|
| 10 |
+ <string-array name="article_arrays"> |
|
| 11 |
+ <item><string name="spinner_default_message">No previous data found</string></item> |
|
| 12 |
+ </string-array> |
|
| 13 |
+ <string name="tags_downloaded">Tags Downloaded</string> |
|
| 14 |
+ <string name="tags_not_found">No Tag Found</string> |
|
| 15 |
+ <string name="tags_not_dl">Tags Not Downloaded yet...</string> |
|
| 16 |
+</resources> |
| ... | ... |
@@ -0,0 +1,6 @@ |
| 1 |
+<resources> |
|
| 2 |
+ <!-- Base application theme. --> |
|
| 3 |
+ <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> |
|
| 4 |
+ <!-- Customize your theme here. --> |
|
| 5 |
+ </style> |
|
| 6 |
+</resources> |
| ... | ... |
@@ -0,0 +1,19 @@ |
| 1 |
+// Top-level build file where you can add configuration options common to all sub-projects/modules. |
|
| 2 |
+ |
|
| 3 |
+buildscript {
|
|
| 4 |
+ repositories {
|
|
| 5 |
+ jcenter() |
|
| 6 |
+ } |
|
| 7 |
+ dependencies {
|
|
| 8 |
+ classpath 'com.android.tools.build:gradle:2.3.3' |
|
| 9 |
+ |
|
| 10 |
+ // NOTE: Do not place your application dependencies here; they belong |
|
| 11 |
+ // in the individual module build.gradle files |
|
| 12 |
+ } |
|
| 13 |
+} |
|
| 14 |
+ |
|
| 15 |
+allprojects {
|
|
| 16 |
+ repositories {
|
|
| 17 |
+ jcenter() |
|
| 18 |
+ } |
|
| 19 |
+} |
| ... | ... |
@@ -0,0 +1 @@ |
| 1 |
+include ':app' |