if JAVA
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaCodec;
import android.media.MediaDescription;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMetadata;
import android.media.MediaMetadataRetriever;
import android.media.RemoteControlClient.MetadataEditor;
import android.media.RemoteControlClient;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.os.Binder;
import android.os.Build.VERSION;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.ResultReceiver;
import android.os.SystemClock;
import android.service.media.MediaBrowserService.Result;
import android.app.Notification;
//import android.support.v4.app.NotificationCompat;
//import android.support.v4.app.NotificationCompat.Style;
//import android.support.v4.app.NotificationCompat.Builder;
//import android.support.v4.media.app.NotificationCompat.MediaStyle;
//import android.support.v4.media.MediaBrowserCompat;
//import android.support.v4.media.MediaBrowserCompat.MediaItem;
//import android.support.v4.media.MediaBrowserServiceCompat;
//import android.support.v4.media.MediaMetadataCompat;
//import android.support.v4.media.session.MediaButtonReceiver;
//import android.support.v4.media.session.MediaSessionCompat.*;
//import android.support.v4.media.session.MediaSessionCompat;
//import android.support.v4.media.session.PlaybackStateCompat.*;
//import android.support.v4.media.session.PlaybackStateCompat;
//import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
//import android.support.v7.media.MediaItemMetadata;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationCompat.Style;
import androidx.core.app.NotificationCompat.Builder;
import androidx.media.app.NotificationCompat.MediaStyle;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaBrowserCompat.MediaItem;
import androidx.media.MediaBrowserServiceCompat;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.MediaMetadataCompat;
import androidx.media.session.MediaButtonReceiver;
import android.support.v4.media.session.MediaSessionCompat.*;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat.*;
import android.support.v4.media.session.PlaybackStateCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.mediarouter.media.MediaItemMetadata;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.format.Time;
import android.util.Log;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.objects.IntentWrapper;
import com.google.android.gms.cast.TextTrackStyle;
import java.util.ArrayList;
import java.util.List;
private AudioManager mAudioManager;
private AudioTrack mAudioTrack;
private RemoteControlClient mRemoteControlClient;
private MediaSessionCompat mMediaSession;
//private MediaBrowserCompat mMediaBrowser;
//----------------------------------------------------------------------
// _onCreate Is called whenever Activity Is alive
//----------------------------------------------------------------------
public void _onCreate() {
BA.Log("Running onCreate");
}
//----------------------------------------------------------------------
// mediaSessionStart will setup needed classes
//----------------------------------------------------------------------
public void mediaSessionStart() {
BA.Log("mediaSessionStart");
IntentFilter filter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
this.mAudioManager = (AudioManager) getSystemService("audio");
if (VERSION.SDK_INT < 21) {
if (this.mRemoteControlClient == null) {
Log.d("init()", "API " + VERSION.SDK_INT + " lower than " + 21);
Log.d("init()", "Using RemoteControlClient API.");
this.mRemoteControlClient = new RemoteControlClient(PendingIntent.getBroadcast(this, 0, new Intent("android.intent.action.MEDIA_BUTTON"), 0));
this.mAudioManager.registerRemoteControlClient(this.mRemoteControlClient);
}
} else if (this.mMediaSession == null) { // My Samsung S7
Log.d("init()", "API " + VERSION.SDK_INT + " greater or equals " + 21);
Log.d("init()", "Using MediaSession API.");
this.mMediaSession = new MediaSessionCompat(this, "MediaSession");
this.mMediaSession.setFlags(2);
this.mMediaSession.setActive(true);
}
}
//----------------------------------------------------------------------
// mediaSessionSetCallBack sets our CallBack routine
//----------------------------------------------------------------------
public void mediaSessionSetCallBack(MediaSessionCompat.Callback callback) {
BA.Log("mediaSessionSetCallBack");
if (this.mMediaSession != null) {
BA.Log("mediaSessionSetCallBack - Setting callback");
this.mMediaSession.setPlaybackState(new PlaybackStateCompat.Builder()
.setActions(PlaybackState.ACTION_STOP | PlaybackState.ACTION_PLAY | PlaybackState.ACTION_PAUSE | PlaybackState.ACTION_SKIP_TO_NEXT | PlaybackState.ACTION_SKIP_TO_PREVIOUS)
.setState(PlaybackState.STATE_STOPPED, -1, TextTrackStyle.DEFAULT_FONT_SCALE, SystemClock.elapsedRealtime())
.build());
this.mMediaSession.setCallback(callback);
}
}
//----------------------------------------------------------------------
// mediaSessionAllDone - releases the callback and clears Active flag
//----------------------------------------------------------------------
public void mediaSessionAllDone() {
BA.Log("mediaSessionAllDone");
if (this.mMediaSession != null) {
BA.Log("mediaSessionAllDone - release");
this.mMediaSession.setPlaybackState(new PlaybackStateCompat.Builder()
.setActions(PlaybackState.ACTION_STOP | PlaybackState.ACTION_PLAY | PlaybackState.ACTION_PAUSE | PlaybackState.ACTION_SKIP_TO_NEXT | PlaybackState.ACTION_SKIP_TO_PREVIOUS)
.setState(PlaybackState.STATE_STOPPED, -1, TextTrackStyle.DEFAULT_FONT_SCALE, SystemClock.elapsedRealtime())
.build());
this.mMediaSession.setActive(false);
this.mMediaSession.release();
this.mMediaSession.setCallback(null);
this.mMediaSession = null;
this.mAudioManager = null;
}
}
//----------------------------------------------------------------------------------
// mediaSessionSetMetadata - Sends the Metadata information to bluetooth device
//----------------------------------------------------------------------------------
public void mediaSessionSetMetadata(Boolean IsPlaying, String Album, String AlbumArtist, String Artist, String Song, long Duration, long TrackNumber, Bitmap bitmap) {
if (VERSION.SDK_INT >= 21) { // My Samsung S7
// BA.Log("sendTrackInfoToBluetoothDevice - >21");
if (AlbumArtist.equalsIgnoreCase("Various Artists") == false) {
Artist = AlbumArtist;
}
// STATE_PLAYING = 3
// STATE_PAUSED = 2
// STATE_STOPPED = 1
// ACTION_STOP = 1
// ACTION_PAUSE = 2
// ACTION_PLAY = 4
// ACTION_SKIP_TO_NEXT = 32
// ACTION_SKIP_TO_PREVIOUS = 16
// ACTION_PLAY_PAUSE = 512
MediaMetadataCompat metadata = new MediaMetadataCompat.Builder()
.putBitmap(MediaMetadata.METADATA_KEY_ART, bitmap)
.putBitmap(MediaMetadata.METADATA_KEY_DISPLAY_ICON, bitmap)
.putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, bitmap)
.putString(MediaMetadata.METADATA_KEY_TITLE, Song)
.putString(MediaMetadata.METADATA_KEY_ARTIST, Artist)
.putString(MediaMetadata.METADATA_KEY_ALBUM, Album)
.putLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER, TrackNumber)
.build();
this.mMediaSession.setMetadata(metadata);
this.mMediaSession.setPlaybackState(new PlaybackStateCompat.Builder()
.setActions(PlaybackState.ACTION_STOP | PlaybackState.ACTION_PLAY | PlaybackState.ACTION_PAUSE | PlaybackState.ACTION_SKIP_TO_NEXT | PlaybackState.ACTION_SKIP_TO_PREVIOUS)
.setState(IsPlaying ? PlaybackState.STATE_PLAYING : PlaybackState.STATE_PAUSED, -1, TextTrackStyle.DEFAULT_FONT_SCALE, SystemClock.elapsedRealtime())
.build());
} else if (VERSION.SDK_INT >= 18) { // My Samsung Tab 3
MediaMetadataRetriever metadata;
android.media.RemoteControlClient.MetadataEditor ed = this.mRemoteControlClient.editMetadata(true);
ed.putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, Album);
ed.putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, Artist);
ed.putString(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, AlbumArtist);
ed.putString(MediaMetadataRetriever.METADATA_KEY_TITLE, Song);
ed.putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, Duration);
ed.putLong(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER, TrackNumber);
ed.apply();
this.mRemoteControlClient.setPlaybackState(3, -1, TextTrackStyle.DEFAULT_FONT_SCALE);
}
}
//----------------------------------------------------------------------------------------
// mediaSessionCallBack extends MediaSessionCompat.Callback
//----------------------------------------------------------------------------------------
public static class mediaSessionCallBack extends MediaSessionCompat.Callback {
public mediaSessionCallBack() {
BA.Log("mediaSessionCallBack");
processBA.raiseEventFromUI(getObject(), "media_callback", null);
}
// public int onStartCommand(Intent intent, int flags, int startId) {
// BA.Log("mediaSession-onStartCommand");
// MediaButtonReceiver.handleIntent(mMediaSession, intent);
// return super.onStartCommand(intent, flags, startId);
// }
public void onCommand(String command, Bundle args, ResultReceiver cb) {
processBA.raiseEventFromUI(null, "media_oncommand", command);
}
public boolean onMediaButtonEvent(Intent mediaButtonIntent) {
IntentWrapper baIntent = new IntentWrapper();
baIntent.setObject(mediaButtonIntent);
Boolean b = (Boolean) processBA.raiseEvent(null, "media_onbutton", baIntent);
return b == null ? false : b;
}
public void onStop() {
processBA.raiseEventFromUI(getObject(), "media_onstop", null);
return;
}
public void onPlay() {
processBA.raiseEventFromUI(getObject(), "media_onplay", null);
return;
}
public void onPause() {
processBA.raiseEventFromUI(getObject(), "media_onpause", null);
return;
}
public void onSkipToNext() {
processBA.raiseEventFromUI(getObject(), "media_onskiptonext", null);
return;
}
public void onSkipToPrevious() {
processBA.raiseEventFromUI(getObject(), "media_onskiptoprevious", null);
return;
}
}
//------------------------------------------------------------------------------------------
// Old BroadcastReceiver - Not currently using was stopping ExitApplication from working
//------------------------------------------------------------------------------------------
public static class MyReceiver extends BroadcastReceiver {
public MyReceiver() {
super();
BA.Log("**** MyReciever");
}
@Override
public void onReceive(Context context, Intent intent) {
IntentWrapper baIntent = new IntentWrapper();
baIntent.setObject(intent);
processBA.raiseEventFromUI(null, "media_onbutton", baIntent);
abortBroadcast();
}
}
#End If
#if _ServerCode_
public static class MyMediaBrowserService extends MediaBrowserServiceCompat {
private final String MEDIA_ID_ROOT = "__ROOT__";
private final String MY_EMPTY_MEDIA_ROOT_ID = "__Empty_Root__";
public int onStartCommand(Intent intent, int flags, int startId) {
try {
//An audio file is passed to the service through putExtra();
// mediaFile = intent.getExtras().getString("media");
} catch (NullPointerException e) {
// stopSelf();
}
return onStartCommand(intent, flags, startId);
}
public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
BA.Log("MyMediaBrowserService - OnGetRoot");
processBA.raiseEventFromUI(getObject(), "media_ongetroot", clientPackageName);
return new BrowserRoot(MEDIA_ID_ROOT, null);
}
public void onLoadChildren(String parentMediaId, Result<List<MediaItem>> result) {
// I promise we’ll get To browsing
BA.Log("MyMediaBrowserService - OnLoadChildren");
processBA.raiseEventFromUI(getObject(), "media_onloadchildren", parentMediaId);
result.sendResult(null);
}
}
#end if