Browse Source

Merge branch 'testing'

# Conflicts:
#	app/src/main/java/fr/svpro/radiomercure/MainActivity.java
master
Samuel Vermeulen 5 months ago
parent
commit
c618afe059
  1. 17
      .idea/deploymentTargetDropDown.xml
  2. 4
      .idea/misc.xml
  3. 4
      app/build.gradle
  4. 5
      app/src/main/AndroidManifest.xml
  5. 2
      app/src/main/java/fr/svpro/radiomercure/MainActivity.java
  6. 268
      app/src/main/java/fr/svpro/radiomercure/MediaPlayerService.java
  7. 10
      app/src/main/res/layout/activity_main.xml
  8. 7
      app/src/main/res/menu/option.xml
  9. 12
      app/src/main/res/values/strings.xml

17
.idea/deploymentTargetDropDown.xml

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="C:\Users\samue\.android\avd\Nexus_6_API_29.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2022-03-31T21:48:44.877184900Z" />
</component>
</project>

4
.idea/misc.xml

@ -4,8 +4,8 @@
<option name="filePathToZoomLevelMap">
<map>
<entry key="..\:/Users/samue/GIT/RadioMercure/app/src/main/res/drawable/ic_launcher_background.xml" value="0.2355" />
<entry key="..\:/Users/samue/GIT/RadioMercure/app/src/main/res/layout/about_dialog.xml" value="0.2" />
<entry key="..\:/Users/samue/GIT/RadioMercure/app/src/main/res/layout/activity_main.xml" value="0.11402623612512613" />
<entry key="..\:/Users/samue/GIT/RadioMercure/app/src/main/res/layout/about_dialog.xml" value="0.5" />
<entry key="..\:/Users/samue/GIT/RadioMercure/app/src/main/res/layout/activity_main.xml" value="0.1755050505050505" />
<entry key="..\:/Users/samue/GIT/RadioMercure/app/src/main/res/menu/option.xml" value="0.33" />
</map>
</option>

4
app/build.gradle

@ -22,8 +22,8 @@ android {
applicationId "fr.svpro.radiomercure"
minSdk 22
targetSdk 31
versionCode 103
versionName '1.0.3'
versionCode 110
versionName '1.1.0'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

5
app/src/main/AndroidManifest.xml

@ -4,6 +4,10 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<application
android:allowBackup="true"
@ -23,6 +27,7 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MediaPlayerService"/>
</application>
</manifest>

2
app/src/main/java/fr/svpro/radiomercure/MainActivity.java

@ -10,9 +10,11 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.CookieManager;
import android.webkit.DownloadListener;
import android.webkit.URLUtil;
import android.webkit.WebSettings;
import android.webkit.WebView;

268
app/src/main/java/fr/svpro/radiomercure/MediaPlayerService.java

@ -0,0 +1,268 @@
package fr.svpro.radiomercure;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
import java.io.IOException;
@RequiresApi(api = Build.VERSION_CODES.O)
public class MediaPlayerService extends Service implements MediaPlayer.OnCompletionListener,
MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnSeekCompleteListener,
MediaPlayer.OnInfoListener, MediaPlayer.OnBufferingUpdateListener,
AudioManager.OnAudioFocusChangeListener {
private AudioManager audioManager;
// Binder given to clients
private final IBinder iBinder = new LocalBinder();
@Override
public IBinder onBind(Intent intent) {
return iBinder;
}
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
//Invoked indicating buffering status of
//a media resource being streamed over the network.
}
@Override
public void onCompletion(MediaPlayer mp) {
//Invoked when playback of a media source has completed.
stopMedia();
//stop the service
stopSelf();
}
//Handle errors
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
//Invoked when there has been an error during an asynchronous operation
switch (what) {
case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
Toast.makeText(this, "Données corrompues", Toast.LENGTH_SHORT).show();
Log.d("MediaPlayer Error", "MEDIA ERROR NOT VALID FOR PROGRESSIVE PLAYBACK " + extra);
break;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
Toast.makeText(this, "Serveur innacessible", Toast.LENGTH_SHORT).show();
Log.d("MediaPlayer Error", "MEDIA ERROR SERVER DIED " + extra);
break;
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
Toast.makeText(this, "Erreur inconnue", Toast.LENGTH_SHORT).show();
Log.d("MediaPlayer Error", "MEDIA ERROR UNKNOWN " + extra);
break;
}
return false;
}
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
//Invoked to communicate some info.
return false;
}
@Override
public void onPrepared(MediaPlayer mp) {
playMedia();
}
@Override
public void onSeekComplete(MediaPlayer mp) {
//Invoked indicating the completion of a seek operation.
}
@Override
public void onAudioFocusChange(int focusState) {
//Invoked when the audio focus of the system is updated.
switch (focusState) {
case AudioManager.AUDIOFOCUS_GAIN:
// resume playback
if (mediaPlayer == null) initMediaPlayer();
else if (!mediaPlayer.isPlaying()) mediaPlayer.start();
mediaPlayer.setVolume(1.0f, 1.0f);
break;
case AudioManager.AUDIOFOCUS_LOSS:
// Lost focus for an unbounded amount of time: stop playback and release media player
if (mediaPlayer.isPlaying()) mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
// Lost focus for a short time, but we have to stop
// playback. We don't release the media player because playback
// is likely to resume
if (mediaPlayer.isPlaying()) mediaPlayer.pause();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
// Lost focus for a short time, but it's ok to keep playing
// at an attenuated level
if (mediaPlayer.isPlaying()) mediaPlayer.setVolume(0.1f, 0.1f);
break;
}
}
private boolean requestAudioFocus() {
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
//Focus gained
return true;
}
//Could not gain focus
return false;
}
private boolean removeAudioFocus() {
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
audioManager.abandonAudioFocus(this);
}
public class LocalBinder extends Binder {
public MediaPlayerService getService() {
return MediaPlayerService.this;
}
}
private MediaPlayer mediaPlayer;
private String fichierMedia;
private void initMediaPlayer() {
mediaPlayer = new MediaPlayer();
//Set up MediaPlayer event listeners
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnSeekCompleteListener(this);
mediaPlayer.setOnInfoListener(this);
//mediaPlayer.setScreenOnWhilePlaying(true);
//Reset so that the MediaPlayer is not pointing to another data source
mediaPlayer.reset();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(fichierMedia);
} catch (IOException e) {
e.printStackTrace();
stopSelf();
}
mediaPlayer.prepareAsync();
}
//Used to pause/resume MediaPlayer
private int resumePosition;
private void playMedia() {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
}
private void stopMedia() {
if (mediaPlayer == null) return;
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
}
private void pauseMedia() {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
resumePosition = mediaPlayer.getCurrentPosition();
}
}
private void resumeMedia() {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.seekTo(resumePosition);
mediaPlayer.start();
}
}
//The system calls this method when an activity, requests the service be started
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
//An audio file is passed to the service through putExtra();
fichierMedia = intent.getExtras().getString("media");
} catch (NullPointerException e) {
stopSelf();
}
//Request audio focus
if (requestAudioFocus() == false) {
//Could not gain focus
stopSelf();
}
if (fichierMedia != null && fichierMedia != "")
initMediaPlayer();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
if (mediaPlayer != null) {
stopMedia();
mediaPlayer.release();
}
removeAudioFocus();
}
//Gestion des appels tel entrant : suspension de la lecture
private boolean ongoingCall = false;
private PhoneStateListener phoneStateListener;
private TelephonyManager telephonyManager;
private void callStateListener() {
// Get the telephony manager
telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
//Starting listening for PhoneState changes
phoneStateListener = new PhoneStateListener() {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
//if at least one call exists or the phone is ringing
//pause the MediaPlayer
case TelephonyManager.CALL_STATE_OFFHOOK:
case TelephonyManager.CALL_STATE_RINGING:
if (mediaPlayer != null) {
pauseMedia();
ongoingCall = true;
}
break;
case TelephonyManager.CALL_STATE_IDLE:
// Phone idle. Start playing.
if (mediaPlayer != null) {
if (ongoingCall) {
ongoingCall = false;
resumeMedia();
}
}
break;
}
}
};
// Register the listener with the telephony manager
// Listen for changes to the device call state.
telephonyManager.listen(phoneStateListener,
PhoneStateListener.LISTEN_CALL_STATE);
}
}

10
app/src/main/res/layout/activity_main.xml

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -9,5 +8,8 @@
<WebView
android:id="@+id/wv"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
android:layout_height="match_parent">
</WebView>
</RelativeLayout>

7
app/src/main/res/menu/option.xml

@ -10,11 +10,18 @@
android:id="@+id/refresh"
android:title="@string/menu_reload" />
<item
android:id="@+id/live"
android:icon="@android:drawable/ic_media_play"
app:showAsAction="ifRoom"
android:title="@string/menu_live" />
<item
android:id="@+id/tel"
android:icon="@android:drawable/stat_sys_phone_call"
android:title="@string/menu_phone"
app:showAsAction="ifRoom" />
<item
android:id="@+id/exit"
android:icon="@android:drawable/ic_lock_power_off"

12
app/src/main/res/values/strings.xml

@ -2,8 +2,20 @@
<string name="app_name">Radio Mercure</string>
<string name="menu_exit">Quitter</string>
<string name="menu_phone">Appeler la Radio</string>
<string name="menu_live">Ecouter en direct</string>
<string name="menu_reload">Relancer...</string>
<string name="menu_about">A Propos...</string>
<string name="dialog_close">Fermer</string>
<string name="dialog_version">RADIO MERCURE - Version </string>
<string name="dialog_battery_msg"><![CDATA[Dans le cadre d\'une utilisation optimiale de RADIO MERCURE en arrière-plan notamment pour la lecture du direct,
il est nécessaire de retirer l\'application de la liste des applications optimisées.
En cliquant sur \"Oui\", la fenêtre \"Optimiser la batterie\" apparaît puis :\n
- Selectionnez \"Tout\"\n
- Recherchez \"Radio Mercure\"\n
- Déchochez\n
- Revenez en arrière jusqu\'à afficher l\'application
]]></string>
<string name="dialog_battery_titre">Désactiver l\'optimisation de la batterie ?</string>
<string name="dialog_button_oui">Oui</string>
<string name="dialog_button_non">Non</string>
</resources>
Loading…
Cancel
Save