Browse Source

Merge branch 'devel'

yattoz 2 years ago
parent
commit
24edc08bbf

+ 1 - 0
.idea/gradle.xml View File

7
         <option name="testRunner" value="GRADLE" />
7
         <option name="testRunner" value="GRADLE" />
8
         <option name="distributionType" value="DEFAULT_WRAPPED" />
8
         <option name="distributionType" value="DEFAULT_WRAPPED" />
9
         <option name="externalProjectPath" value="$PROJECT_DIR$" />
9
         <option name="externalProjectPath" value="$PROJECT_DIR$" />
10
+        <option name="gradleJvm" value="Android Studio default JDK" />
10
         <option name="modules">
11
         <option name="modules">
11
           <set>
12
           <set>
12
             <option value="$PROJECT_DIR$" />
13
             <option value="$PROJECT_DIR$" />

+ 5 - 0
.idea/jarRepositories.xml View File

26
       <option name="name" value="Google" />
26
       <option name="name" value="Google" />
27
       <option name="url" value="https://dl.google.com/dl/android/maven2/" />
27
       <option name="url" value="https://dl.google.com/dl/android/maven2/" />
28
     </remote-repository>
28
     </remote-repository>
29
+    <remote-repository>
30
+      <option name="id" value="MavenRepo" />
31
+      <option name="name" value="MavenRepo" />
32
+      <option name="url" value="https://repo.maven.apache.org/maven2/" />
33
+    </remote-repository>
29
   </component>
34
   </component>
30
 </project>
35
 </project>

+ 1 - 1
.idea/misc.xml View File

1
 <?xml version="1.0" encoding="UTF-8"?>
1
 <?xml version="1.0" encoding="UTF-8"?>
2
 <project version="4">
2
 <project version="4">
3
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
3
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="1.8" project-jdk-type="JavaSDK">
4
     <output url="file://$PROJECT_DIR$/build/classes" />
4
     <output url="file://$PROJECT_DIR$/build/classes" />
5
   </component>
5
   </component>
6
   <component name="ProjectType">
6
   <component name="ProjectType">

+ 18 - 12
app/build.gradle View File

16
 }
16
 }
17
 
17
 
18
 android {
18
 android {
19
-    compileSdkVersion 30
20
-    buildToolsVersion "30.0.1"
19
+    compileSdkVersion 32
21
     compileOptions {
20
     compileOptions {
22
-        sourceCompatibility JavaVersion.VERSION_1_8
23
-        targetCompatibility JavaVersion.VERSION_1_8
21
+        sourceCompatibility JavaVersion.VERSION_11
22
+        targetCompatibility JavaVersion.VERSION_11
24
     }
23
     }
25
     kotlinOptions {
24
     kotlinOptions {
26
-        jvmTarget = "1.8"
25
+        jvmTarget = "11"
27
     }
26
     }
28
     defaultConfig {
27
     defaultConfig {
29
         applicationId "fr.forum_thalie.tsumugi"
28
         applicationId "fr.forum_thalie.tsumugi"
30
         minSdkVersion 16
29
         minSdkVersion 16
31
-        targetSdkVersion 30
32
-        versionCode 120
33
-        versionName "1.2.0"
30
+        targetSdkVersion 32
31
+        multiDexEnabled true
32
+        versionCode 121
33
+        versionName "1.2.1"
34
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
34
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
35
         vectorDrawables.useSupportLibrary = true
35
         vectorDrawables.useSupportLibrary = true
36
     }
36
     }
48
 }
48
 }
49
 
49
 
50
 dependencies {
50
 dependencies {
51
+    def multidex_version = "2.0.1"
52
+    implementation "androidx.multidex:multidex:$multidex_version"
53
+
51
     implementation fileTree(dir: 'libs', include: ['*.jar'])
54
     implementation fileTree(dir: 'libs', include: ['*.jar'])
52
     /*
55
     /*
53
     implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
56
     implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
68
 
71
 
69
      */
72
      */
70
 
73
 
71
-    implementation "androidx.media:media:1.1.0"
74
+    implementation "androidx.media:media:1.5.0"
75
+
76
+    //noinspection GradleDependency
72
     implementation 'com.google.android.exoplayer:exoplayer:2.11.3'
77
     implementation 'com.google.android.exoplayer:exoplayer:2.11.3'
78
+
73
     //implementation project(':exoplayer-library') // uses local ExoPlayer clone, from dev-v2 branch (fixes ISO-8859-1 ICY metadata
79
     //implementation project(':exoplayer-library') // uses local ExoPlayer clone, from dev-v2 branch (fixes ISO-8859-1 ICY metadata
74
 
80
 
75
     implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
81
     implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
76
-    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
82
+    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1'
77
 
83
 
78
-    implementation 'androidx.recyclerview:recyclerview:1.1.0'
79
-    implementation 'androidx.preference:preference:1.1.0'
84
+    implementation 'androidx.recyclerview:recyclerview:1.2.1'
85
+    implementation 'androidx.preference:preference-ktx:1.2.0'
80
 
86
 
81
     // jsoup HTML parser library @ https://jsoup.org/
87
     // jsoup HTML parser library @ https://jsoup.org/
82
     // implementation 'org.jsoup:jsoup:1.12.1'
88
     // implementation 'org.jsoup:jsoup:1.12.1'

+ 10 - 7
app/src/main/AndroidManifest.xml View File

10
     <uses-permission android:name="android.permission.BLUETOOTH" />
10
     <uses-permission android:name="android.permission.BLUETOOTH" />
11
     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
11
     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
12
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- needed for API 28 -->
12
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- needed for API 28 -->
13
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
13
+
14
+    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
14
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
15
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
15
     <uses-permission android:name="android.permission.SET_ALARM"/>
16
     <uses-permission android:name="android.permission.SET_ALARM"/>
16
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
17
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
22
         android:label="@string/app_name"
23
         android:label="@string/app_name"
23
         android:supportsRtl="true"
24
         android:supportsRtl="true"
24
         android:theme="@style/AppTheme.Launcher"
25
         android:theme="@style/AppTheme.Launcher"
25
-        tools:ignore="AllowBackup,GoogleAppIndexingWarning">
26
-
26
+        tools:ignore="AllowBackup,GoogleAppIndexingWarning"
27
+        android:name="androidx.multidex.MultiDexApplication">
27
         <service
28
         <service
28
             android:name=".RadioService"
29
             android:name=".RadioService"
29
             android:enabled="true"
30
             android:enabled="true"
35
 
36
 
36
         <receiver android:name=".BootBroadcastReceiver"
37
         <receiver android:name=".BootBroadcastReceiver"
37
             android:directBootAware="true"
38
             android:directBootAware="true"
38
-            tools:targetApi="n">
39
+            tools:targetApi="n"
40
+            android:exported="true">
39
             <intent-filter>
41
             <intent-filter>
40
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
42
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
41
                 <action android:name="fr.forum_thalie.tsumugi.PLAY_OR_FALLBACK" />
43
                 <action android:name="fr.forum_thalie.tsumugi.PLAY_OR_FALLBACK" />
47
         <activity
49
         <activity
48
             android:name=".MainActivity"
50
             android:name=".MainActivity"
49
             android:configChanges="orientation|screenSize"
51
             android:configChanges="orientation|screenSize"
50
-            android:label="@string/app_name"
51
             android:launchMode="singleTask"
52
             android:launchMode="singleTask"
52
-            android:screenOrientation="fullUser">
53
+            android:screenOrientation="fullUser"
54
+            android:exported="true">
53
             <intent-filter>
55
             <intent-filter>
54
                 <action android:name="android.intent.action.MAIN" />
56
                 <action android:name="android.intent.action.MAIN" />
55
 
57
 
63
             android:parentActivityName=".MainActivity"
65
             android:parentActivityName=".MainActivity"
64
             android:screenOrientation="fullUser" />
66
             android:screenOrientation="fullUser" />
65
 
67
 
66
-        <receiver android:name="androidx.media.session.MediaButtonReceiver">
68
+        <receiver android:name="androidx.media.session.MediaButtonReceiver"
69
+            android:exported="true">
67
             <intent-filter>
70
             <intent-filter>
68
                 <action android:name="android.intent.action.MEDIA_BUTTON" />
71
                 <action android:name="android.intent.action.MEDIA_BUTTON" />
69
             </intent-filter>
72
             </intent-filter>

+ 24 - 6
app/src/main/assets/planning_example.json View File

7
       "hour_end": "7:00"
7
       "hour_end": "7:00"
8
     },
8
     },
9
     {
9
     {
10
-      "title": "Jeux Vidéos Matin",
11
-      "periodicity": "1111100",
10
+      "title": "Tsumugi Rétro",
11
+      "periodicity": "1000000",
12
       "hour_begin": "09:00",
12
       "hour_begin": "09:00",
13
-      "hour_end": "10:30"
13
+      "hour_end": "12:00"
14
     },
14
     },
15
     {
15
     {
16
-      "title": "Anime Matin",
17
-      "periodicity": "1111100",
18
-      "hour_begin": "10:30",
16
+      "title": "Tournant du Millénaire",
17
+      "periodicity": "0100000",
18
+      "hour_begin": "09:00",
19
+      "hour_end": "12:00"
20
+    },
21
+    {
22
+      "title": "Tsumugi Netpop",
23
+      "periodicity": "0010000",
24
+      "hour_begin": "09:00",
25
+      "hour_end": "12:00"
26
+    },
27
+    {
28
+      "title": "Tsumugi Moderne",
29
+      "periodicity": "0001000",
30
+      "hour_begin": "09:00",
31
+      "hour_end": "12:00"
32
+    },
33
+    {
34
+      "title": "Tsumugi Très Récent",
35
+      "periodicity": "0000100",
36
+      "hour_begin": "09:00",
19
       "hour_end": "12:00"
37
       "hour_end": "12:00"
20
     },
38
     },
21
     {
39
     {

+ 2 - 1
app/src/main/java/fr/forum_thalie/tsumugi/BaseNotification.kt View File

50
         notificationManager.notify(notificationId, notification)
50
         notificationManager.notify(notificationId, notification)
51
     }
51
     }
52
 
52
 
53
+    @RequiresApi(Build.VERSION_CODES.M)
53
     open fun create(c: Context) {
54
     open fun create(c: Context) {
54
         notificationManager = c.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
55
         notificationManager = c.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
55
 
56
 
58
         // thanks to the launchMode specified in the Manifest : android:launchMode="singleTop"
59
         // thanks to the launchMode specified in the Manifest : android:launchMode="singleTop"
59
         val pendingIntent = PendingIntent.getActivity(
60
         val pendingIntent = PendingIntent.getActivity(
60
             c, 0,
61
             c, 0,
61
-            notificationIntent, 0
62
+            notificationIntent, PendingIntent.FLAG_IMMUTABLE
62
         )
63
         )
63
         var channelID = ""
64
         var channelID = ""
64
 
65
 

+ 8 - 5
app/src/main/java/fr/forum_thalie/tsumugi/NowPlayingNotification.kt View File

3
 import android.app.PendingIntent
3
 import android.app.PendingIntent
4
 import android.content.Context
4
 import android.content.Context
5
 import android.content.Intent
5
 import android.content.Intent
6
+import android.os.Build
6
 import android.support.v4.media.session.MediaSessionCompat
7
 import android.support.v4.media.session.MediaSessionCompat
7
 import android.support.v4.media.session.PlaybackStateCompat
8
 import android.support.v4.media.session.PlaybackStateCompat
9
+import androidx.annotation.RequiresApi
8
 import androidx.core.app.NotificationCompat
10
 import androidx.core.app.NotificationCompat
9
 import fr.forum_thalie.tsumugi.playerstore.PlayerStore
11
 import fr.forum_thalie.tsumugi.playerstore.PlayerStore
10
 
12
 
34
         // got it right
36
         // got it right
35
         val delIntent = Intent(c, RadioService::class.java)
37
         val delIntent = Intent(c, RadioService::class.java)
36
         delIntent.putExtra("action", Actions.KILL.name)
38
         delIntent.putExtra("action", Actions.KILL.name)
37
-        val deleteIntent = PendingIntent.getService(c, 0, delIntent, PendingIntent.FLAG_NO_CREATE)
39
+        val deleteIntent = PendingIntent.getService(c, 0, delIntent, PendingIntent.FLAG_NO_CREATE + PendingIntent.FLAG_IMMUTABLE)
38
         builder.setDeleteIntent(deleteIntent)
40
         builder.setDeleteIntent(deleteIntent)
39
 
41
 
40
         mediaStyle = androidx.media.app.NotificationCompat.DecoratedMediaCustomViewStyle().also {
42
         mediaStyle = androidx.media.app.NotificationCompat.DecoratedMediaCustomViewStyle().also {
46
         update(c)
48
         update(c)
47
     }
49
     }
48
 
50
 
51
+    @RequiresApi(Build.VERSION_CODES.M)
49
     fun update(c: Context, isUpdatingNotificationButton: Boolean = false, isRinging: Boolean = false) {
52
     fun update(c: Context, isUpdatingNotificationButton: Boolean = false, isRinging: Boolean = false) {
50
 
53
 
51
         if (isUpdatingNotificationButton)
54
         if (isUpdatingNotificationButton)
72
 
75
 
73
             playPauseAction = if (PlayerStore.instance.playbackState.value == PlaybackStateCompat.STATE_PLAYING) {
76
             playPauseAction = if (PlayerStore.instance.playbackState.value == PlaybackStateCompat.STATE_PLAYING) {
74
                 intent.putExtra("action", Actions.PAUSE.name)
77
                 intent.putExtra("action", Actions.PAUSE.name)
75
-                val pendingButtonIntent = PendingIntent.getService(c, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT)
78
+                val pendingButtonIntent = PendingIntent.getService(c, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_IMMUTABLE)
76
                 NotificationCompat.Action.Builder(R.drawable.ic_pause, "Pause", pendingButtonIntent).build()
79
                 NotificationCompat.Action.Builder(R.drawable.ic_pause, "Pause", pendingButtonIntent).build()
77
             } else {
80
             } else {
78
                 intent.putExtra("action", Actions.PLAY.name)
81
                 intent.putExtra("action", Actions.PLAY.name)
79
-                val pendingButtonIntent = PendingIntent.getService(c, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT)
82
+                val pendingButtonIntent = PendingIntent.getService(c, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_IMMUTABLE)
80
                 NotificationCompat.Action.Builder(R.drawable.ic_play,"Play", pendingButtonIntent).build()
83
                 NotificationCompat.Action.Builder(R.drawable.ic_play,"Play", pendingButtonIntent).build()
81
             }
84
             }
82
             builder.addAction(playPauseAction)
85
             builder.addAction(playPauseAction)
83
             val intent2 = Intent(c, RadioService::class.java)
86
             val intent2 = Intent(c, RadioService::class.java)
84
             intent2.putExtra("action", Actions.KILL.name)
87
             intent2.putExtra("action", Actions.KILL.name)
85
-            val pendingButtonIntent = PendingIntent.getService(c, 2, intent2, PendingIntent.FLAG_UPDATE_CURRENT)
88
+            val pendingButtonIntent = PendingIntent.getService(c, 2, intent2, PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_IMMUTABLE)
86
             val stopAction = NotificationCompat.Action.Builder(R.drawable.ic_close,"Stop", pendingButtonIntent).build()
89
             val stopAction = NotificationCompat.Action.Builder(R.drawable.ic_close,"Stop", pendingButtonIntent).build()
87
             builder.addAction(stopAction)
90
             builder.addAction(stopAction)
88
 
91
 
92
 
95
 
93
                 val snoozeIntent = Intent(c, RadioService::class.java)
96
                 val snoozeIntent = Intent(c, RadioService::class.java)
94
                 snoozeIntent.putExtra("action", Actions.SNOOZE.name)
97
                 snoozeIntent.putExtra("action", Actions.SNOOZE.name)
95
-                val pendingSnoozeIntent = PendingIntent.getService(c, 5, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT)
98
+                val pendingSnoozeIntent = PendingIntent.getService(c, 5, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_IMMUTABLE)
96
                 val snoozeAction = NotificationCompat.Action.Builder(R.drawable.ic_alarm, "Snooze ($snoozeMinutes min.)", pendingSnoozeIntent ).build()
99
                 val snoozeAction = NotificationCompat.Action.Builder(R.drawable.ic_alarm, "Snooze ($snoozeMinutes min.)", pendingSnoozeIntent ).build()
97
                 if (snoozeMinutes > 0)
100
                 if (snoozeMinutes > 0)
98
                     builder.addAction(snoozeAction)
101
                     builder.addAction(snoozeAction)

+ 7 - 2
app/src/main/java/fr/forum_thalie/tsumugi/RadioService.kt View File

193
 
193
 
194
         // Define managers
194
         // Define managers
195
         telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
195
         telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
196
-        telephonyManager?.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE)
196
+        // telephonyManager?.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE)
197
+
197
         audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
198
         audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
198
 
199
 
199
         //define the audioFocusRequest
200
         //define the audioFocusRequest
514
         if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
515
         if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
515
             return
516
             return
516
         }
517
         }
518
+        if (mediaSession.controller.playbackState.state == PlaybackStateCompat.STATE_PLAYING && !isRinging && isAlarmStopped)
519
+        {
520
+            return //nothing to do here
521
+        }
517
 
522
 
518
         PlayerStore.instance.playbackState.value = PlaybackStateCompat.STATE_PLAYING
523
         PlayerStore.instance.playbackState.value = PlaybackStateCompat.STATE_PLAYING
519
 
524
 
530
         }
535
         }
531
 
536
 
532
         // START PLAYBACK, LET'S ROCK
537
         // START PLAYBACK, LET'S ROCK
538
+        player.playWhenReady = true
533
         nowPlayingNotification.update(this, isUpdatingNotificationButton =  true, isRinging = isRinging)
539
         nowPlayingNotification.update(this, isUpdatingNotificationButton =  true, isRinging = isRinging)
534
 
540
 
535
         playbackStateBuilder.setState(
541
         playbackStateBuilder.setState(
539
             SystemClock.elapsedRealtime()
545
             SystemClock.elapsedRealtime()
540
         )
546
         )
541
         mediaSession.setPlaybackState(playbackStateBuilder.build())
547
         mediaSession.setPlaybackState(playbackStateBuilder.build())
542
-        player.playWhenReady = true
543
 
548
 
544
         //[REMOVE LOG CALLS]Log.d(tag, radioTag + "begin playing")
549
         //[REMOVE LOG CALLS]Log.d(tag, radioTag + "begin playing")
545
     }
550
     }

+ 24 - 3
app/src/main/java/fr/forum_thalie/tsumugi/alarm/RadioAlarm.kt View File

4
 import android.app.PendingIntent
4
 import android.app.PendingIntent
5
 import android.content.Context
5
 import android.content.Context
6
 import android.content.Intent
6
 import android.content.Intent
7
+import android.os.Build
7
 import android.util.Log
8
 import android.util.Log
9
+import androidx.annotation.RequiresApi
8
 import androidx.core.app.AlarmManagerCompat
10
 import androidx.core.app.AlarmManagerCompat
9
 import fr.forum_thalie.tsumugi.BootBroadcastReceiver
11
 import fr.forum_thalie.tsumugi.BootBroadcastReceiver
10
 import androidx.preference.PreferenceManager
12
 import androidx.preference.PreferenceManager
27
     {
29
     {
28
         alarmIntent = Intent(c, BootBroadcastReceiver::class.java).let { intent ->
30
         alarmIntent = Intent(c, BootBroadcastReceiver::class.java).let { intent ->
29
             intent.putExtra("action", "$tag.${Actions.PLAY_OR_FALLBACK.name}")
31
             intent.putExtra("action", "$tag.${Actions.PLAY_OR_FALLBACK.name}")
30
-            PendingIntent.getBroadcast(c, 0, intent, 0)
32
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
33
+                PendingIntent.getBroadcast(
34
+                    c,
35
+                    0,
36
+                    intent,
37
+                    PendingIntent.FLAG_IMMUTABLE
38
+                )
39
+            } else {
40
+                PendingIntent.getBroadcast(
41
+                    c,
42
+                    0,
43
+                    intent,
44
+                    0
45
+                )
46
+            }
31
         }
47
         }
32
         showIntent = Intent(c, ParametersActivity::class.java).let { intent ->
48
         showIntent = Intent(c, ParametersActivity::class.java).let { intent ->
33
             intent.putExtra("action", "alarm")
49
             intent.putExtra("action", "alarm")
34
-            PendingIntent.getActivity(c, 0, intent, 0)
50
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
51
+                PendingIntent.getActivity(c, 0, intent, PendingIntent.FLAG_IMMUTABLE)
52
+            } else {
53
+                PendingIntent.getActivity(c, 0, intent, 0)
54
+            }
35
         }
55
         }
36
     }
56
     }
37
 
57
 
43
         alarmManager.cancel(alarmIntent)
63
         alarmManager.cancel(alarmIntent)
44
     }
64
     }
45
 
65
 
66
+    @RequiresApi(Build.VERSION_CODES.M)
46
     fun setNextAlarm(c: Context, isForce: Boolean = false, forceTime: Int? = null, forceDays: Set<String>? = null)
67
     fun setNextAlarm(c: Context, isForce: Boolean = false, forceTime: Int? = null, forceDays: Set<String>? = null)
47
     {
68
     {
48
         defineIntents(c)
69
         defineIntents(c)
54
 
75
 
55
         val showIntent = Intent(c, ParametersActivity::class.java).let { intent ->
76
         val showIntent = Intent(c, ParametersActivity::class.java).let { intent ->
56
             intent.putExtra("action", ActionOpenParam.ALARM.name)
77
             intent.putExtra("action", ActionOpenParam.ALARM.name)
57
-            PendingIntent.getActivity(c, 0, intent, 0)
78
+            PendingIntent.getActivity(c, 0, intent, PendingIntent.FLAG_IMMUTABLE)
58
         }
79
         }
59
         val time = findNextAlarmTime(c, forceTime, forceDays)
80
         val time = findNextAlarmTime(c, forceTime, forceDays)
60
         if (time > 0)
81
         if (time > 0)

+ 6 - 2
app/src/main/java/fr/forum_thalie/tsumugi/alarm/RadioSleeper.kt View File

4
 import android.app.PendingIntent
4
 import android.app.PendingIntent
5
 import android.content.Context
5
 import android.content.Context
6
 import android.content.Intent
6
 import android.content.Intent
7
+import android.os.Build
7
 import android.util.Log
8
 import android.util.Log
9
+import androidx.annotation.RequiresApi
8
 import androidx.core.app.AlarmManagerCompat
10
 import androidx.core.app.AlarmManagerCompat
9
 import androidx.lifecycle.MutableLiveData
11
 import androidx.lifecycle.MutableLiveData
10
 import androidx.preference.PreferenceManager
12
 import androidx.preference.PreferenceManager
30
     private lateinit var sleepIntent: PendingIntent
32
     private lateinit var sleepIntent: PendingIntent
31
     private lateinit var fadeOutIntent: PendingIntent
33
     private lateinit var fadeOutIntent: PendingIntent
32
 
34
 
35
+    @RequiresApi(Build.VERSION_CODES.M)
33
     private fun defineIntents(c: Context)
36
     private fun defineIntents(c: Context)
34
     {
37
     {
35
         sleepIntent = Intent(c, RadioService::class.java).let { intent ->
38
         sleepIntent = Intent(c, RadioService::class.java).let { intent ->
36
             intent.putExtra("action", Actions.KILL.name)
39
             intent.putExtra("action", Actions.KILL.name)
37
-            PendingIntent.getService(c, 99, intent, 0)
40
+            PendingIntent.getService(c, 99, intent, PendingIntent.FLAG_IMMUTABLE)
38
         }
41
         }
39
         fadeOutIntent = Intent(c, RadioService::class.java).let { intent ->
42
         fadeOutIntent = Intent(c, RadioService::class.java).let { intent ->
40
             intent.putExtra("action", Actions.FADE_OUT.name)
43
             intent.putExtra("action", Actions.FADE_OUT.name)
41
-            PendingIntent.getService(c, 98, intent, 0)
44
+            PendingIntent.getService(c, 98, intent, PendingIntent.FLAG_IMMUTABLE)
42
         }
45
         }
43
     }
46
     }
44
 
47
 
48
+    @RequiresApi(Build.VERSION_CODES.M)
45
     fun setSleep(c: Context, isForce: Boolean = false, forceDuration: Long? = null)
49
     fun setSleep(c: Context, isForce: Boolean = false, forceDuration: Long? = null)
46
     {
50
     {
47
         defineIntents(c)
51
         defineIntents(c)

+ 15 - 15
app/src/main/java/fr/forum_thalie/tsumugi/preferences/AlarmFragment.kt View File

47
 
47
 
48
         fun updateIsWakingUpSummary(preference: SwitchPreferenceCompat?, newValue: Boolean? = true,  forceTime: Int? = null, forceDays: Set<String>? = null)
48
         fun updateIsWakingUpSummary(preference: SwitchPreferenceCompat?, newValue: Boolean? = true,  forceTime: Int? = null, forceDays: Set<String>? = null)
49
         {
49
         {
50
-            val dateLong = RadioAlarm.instance.findNextAlarmTime(context!!, forceTime, forceDays)
50
+            val dateLong = RadioAlarm.instance.findNextAlarmTime(requireContext(), forceTime, forceDays)
51
             val calendar = Calendar.getInstance()
51
             val calendar = Calendar.getInstance()
52
             calendar.timeInMillis = dateLong
52
             calendar.timeInMillis = dateLong
53
             if (newValue == true && calendar.timeInMillis > 0)
53
             if (newValue == true && calendar.timeInMillis > 0)
65
 
65
 
66
         val hourOfDayDefault = 7
66
         val hourOfDayDefault = 7
67
         val minuteDefault = 0
67
         val minuteDefault = 0
68
-        if (!PreferenceManager.getDefaultSharedPreferences(context!!).contains("alarmTimeFromMidnight"))
68
+        if (!PreferenceManager.getDefaultSharedPreferences(requireContext()).contains("alarmTimeFromMidnight"))
69
         {
69
         {
70
-            PreferenceManager.getDefaultSharedPreferences(context!!).edit {
70
+            PreferenceManager.getDefaultSharedPreferences(requireContext()).edit {
71
                 putInt("alarmTimeFromMidnight", (60*hourOfDayDefault+minuteDefault))
71
                 putInt("alarmTimeFromMidnight", (60*hourOfDayDefault+minuteDefault))
72
                 commit()
72
                 commit()
73
             }
73
             }
74
         }
74
         }
75
-        val time = PreferenceManager.getDefaultSharedPreferences(context!!).getInt("alarmTimeFromMidnight", (60*hourOfDayDefault+minuteDefault))
75
+        val time = PreferenceManager.getDefaultSharedPreferences(requireContext()).getInt("alarmTimeFromMidnight", (60*hourOfDayDefault+minuteDefault))
76
         val hourOfDay = time / 60
76
         val hourOfDay = time / 60
77
         val minute = time % 60
77
         val minute = time % 60
78
         timeSet?.summary = "${if (hourOfDay < 10) "0" else ""}$hourOfDay:${if (minute < 10) "0" else ""}$minute"
78
         timeSet?.summary = "${if (hourOfDay < 10) "0" else ""}$hourOfDay:${if (minute < 10) "0" else ""}$minute"
80
 
80
 
81
         timeSet?.setOnPreferenceClickListener {
81
         timeSet?.setOnPreferenceClickListener {
82
             val timePickerOnTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hourOfDay, minute ->
82
             val timePickerOnTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hourOfDay, minute ->
83
-                PreferenceManager.getDefaultSharedPreferences(context!!).edit {
83
+                PreferenceManager.getDefaultSharedPreferences(requireContext()).edit {
84
                     putInt("alarmTimeFromMidnight", (60*hourOfDay+minute))
84
                     putInt("alarmTimeFromMidnight", (60*hourOfDay+minute))
85
                     commit()
85
                     commit()
86
                 }
86
                 }
87
                 timeSet.summary = "${if (hourOfDay < 10) "0" else ""}$hourOfDay:${if (minute < 10) "0" else ""}$minute"
87
                 timeSet.summary = "${if (hourOfDay < 10) "0" else ""}$hourOfDay:${if (minute < 10) "0" else ""}$minute"
88
-                RadioAlarm.instance.cancelAlarm(context!!)
89
-                RadioAlarm.instance.setNextAlarm(context!!, isForce = true, forceTime = hourOfDay*60+minute)
88
+                RadioAlarm.instance.cancelAlarm(requireContext())
89
+                RadioAlarm.instance.setNextAlarm(requireContext(), isForce = true, forceTime = hourOfDay*60+minute)
90
                 updateIsWakingUpSummary(isWakingUp, isWakingUp?.isChecked, forceTime = hourOfDay*60+minute)
90
                 updateIsWakingUpSummary(isWakingUp, isWakingUp?.isChecked, forceTime = hourOfDay*60+minute)
91
             }
91
             }
92
-            val timeNew = PreferenceManager.getDefaultSharedPreferences(context!!).getInt("alarmTimeFromMidnight", 7*60)
92
+            val timeNew = PreferenceManager.getDefaultSharedPreferences(requireContext()).getInt("alarmTimeFromMidnight", 7*60)
93
             val hourOfDayNew = timeNew / 60
93
             val hourOfDayNew = timeNew / 60
94
             val minuteNew = timeNew % 60
94
             val minuteNew = timeNew % 60
95
             val timePicker = TimePickerDialog(context, timePickerOnTimeSetListener, hourOfDayNew, minuteNew, true)
95
             val timePicker = TimePickerDialog(context, timePickerOnTimeSetListener, hourOfDayNew, minuteNew, true)
103
             val fullWeek = weekdays.toSet()
103
             val fullWeek = weekdays.toSet()
104
             val workingWeek = weekdays.toSet().minusElement(weekdays.last()).minusElement(weekdays.elementAt(weekdays.size - 2))
104
             val workingWeek = weekdays.toSet().minusElement(weekdays.last()).minusElement(weekdays.elementAt(weekdays.size - 2))
105
             val listOfDays = when (newValue) {
105
             val listOfDays = when (newValue) {
106
-                fullWeek -> context!!.getString(R.string.every_day)
107
-                workingWeek -> context!!.getString(R.string.working_days)
106
+                fullWeek -> requireContext().getString(R.string.every_day)
107
+                workingWeek -> requireContext().getString(R.string.working_days)
108
                 else -> {
108
                 else -> {
109
                     // build ORDERED LIST of days... I don't know why the original one is in shambles!!
109
                     // build ORDERED LIST of days... I don't know why the original one is in shambles!!
110
                     val fullWeekOrdered = weekdays
110
                     val fullWeekOrdered = weekdays
119
             preference?.summary = listOfDays
119
             preference?.summary = listOfDays
120
         }
120
         }
121
 
121
 
122
-        updateDays(alarmDays, PreferenceManager.getDefaultSharedPreferences(context).getStringSet("alarmDays", setOf()))
122
+        updateDays(alarmDays, PreferenceManager.getDefaultSharedPreferences(requireContext()).getStringSet("alarmDays", setOf()))
123
         alarmDays?.setOnPreferenceChangeListener { preference, newValue ->
123
         alarmDays?.setOnPreferenceChangeListener { preference, newValue ->
124
             @Suppress("UNCHECKED_CAST")
124
             @Suppress("UNCHECKED_CAST")
125
             updateDays(preference as MultiSelectListPreference, newValue as Set<String>)
125
             updateDays(preference as MultiSelectListPreference, newValue as Set<String>)
126
-            RadioAlarm.instance.cancelAlarm(context!!)
127
-            RadioAlarm.instance.setNextAlarm(context!!, isForce = true, forceDays = newValue)
126
+            RadioAlarm.instance.cancelAlarm(requireContext())
127
+            RadioAlarm.instance.setNextAlarm(requireContext(), isForce = true, forceDays = newValue)
128
             updateIsWakingUpSummary(isWakingUp, isWakingUp?.isChecked, forceDays = newValue)
128
             updateIsWakingUpSummary(isWakingUp, isWakingUp?.isChecked, forceDays = newValue)
129
             true
129
             true
130
         }
130
         }
133
 
133
 
134
         isWakingUp?.setOnPreferenceChangeListener { _, newValue ->
134
         isWakingUp?.setOnPreferenceChangeListener { _, newValue ->
135
             if (newValue as Boolean)
135
             if (newValue as Boolean)
136
-                RadioAlarm.instance.setNextAlarm(context!!, isForce = true)
136
+                RadioAlarm.instance.setNextAlarm(requireContext(), isForce = true)
137
             else
137
             else
138
-                RadioAlarm.instance.cancelAlarm(context!!)
138
+                RadioAlarm.instance.cancelAlarm(requireContext())
139
             timeSet?.isEnabled = newValue
139
             timeSet?.isEnabled = newValue
140
             alarmDays?.isEnabled = newValue
140
             alarmDays?.isEnabled = newValue
141
             snoozeDuration?.isEnabled = newValue
141
             snoozeDuration?.isEnabled = newValue

+ 3 - 2
build.gradle View File

1
 // Top-level build file where you can add configuration options common to all sub-projects/modules.
1
 // Top-level build file where you can add configuration options common to all sub-projects/modules.
2
 
2
 
3
 buildscript {
3
 buildscript {
4
-    ext.kotlin_version = '1.3.72'
4
+    ext.kotlin_version = '1.6.10'
5
     repositories {
5
     repositories {
6
         google()
6
         google()
7
         jcenter()
7
         jcenter()
8
     }
8
     }
9
     dependencies {
9
     dependencies {
10
-        classpath 'com.android.tools.build:gradle:4.0.1'
10
+        classpath 'com.android.tools.build:gradle:7.1.2'
11
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
12
         // NOTE: Do not place your application dependencies here; they belong
12
         // NOTE: Do not place your application dependencies here; they belong
13
         // in the individual module build.gradle files
13
         // in the individual module build.gradle files
14
+
14
     }
15
     }
15
 }
16
 }
16
 
17
 

+ 1 - 1
gradle/wrapper/gradle-wrapper.properties View File

3
 distributionPath=wrapper/dists
3
 distributionPath=wrapper/dists
4
 zipStoreBase=GRADLE_USER_HOME
4
 zipStoreBase=GRADLE_USER_HOME
5
 zipStorePath=wrapper/dists
5
 zipStorePath=wrapper/dists
6
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
6
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip