Android Question SEND TEXT --> DISPLAY BLUETOOTH

MarcoRome

Expert
Licensed User
Longtime User
Hi all.
How can i send a string to a bluetooth device (device type of the car, advertising billboards, etc) that simply displays the string sent ??

Example i have this string: "Hi today is xx/yy/zzzz, you have discount XX%".
This message should be displayed on the device.
Thank you
Marco
 

MarcoRome

Expert
Licensed User
Longtime User
The protocol is A2DP
I found this code that work:

B4X:
            if (this.mAudioManager.isBluetoothA2dpOn()) {
                sendTrackInfoToBluetoothDevice();
            }
        }
    }

    public void sendTrackInfoToBluetoothDevice() {
        if (VERSION.SDK_INT >= 21) {
            this.mMediaSession.setMetadata(new MediaMetadata.Builder().putString(MediaItemMetadata.KEY_TITLE, this.mUserData.getPlayingTitle()).putString(MediaItemMetadata.KEY_ARTIST, this.mUserData.getPlayingArtist()).putString(MediaMetadataCompat.METADATA_KEY_ALBUM, this.mUserData.getPlayingAlbumTitle()).build());
            this.mMediaSession.setPlaybackState(new PlaybackState.Builder().setActions(4).setState(3, -1, TextTrackStyle.DEFAULT_FONT_SCALE, SystemClock.elapsedRealtime()).build());
        } else if (VERSION.SDK_INT >= 18) {
            MetadataEditor ed = this.mRemoteControlClient.editMetadata(true);
            ed.putString(7, this.mUserData.getPlayingTitle());
            ed.putString(2, this.mUserData.getPlayingArtist());
            ed.putString(1, this.mUserData.getPlayingAlbumTitle());
            ed.apply();
            this.mRemoteControlClient.setPlaybackState(3, -1, TextTrackStyle.DEFAULT_FONT_SCALE);
        }
    }

Is it possbile translate in B4A ?
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
Upvote 0

MarcoRome

Expert
Licensed User
Longtime User
Where do mMediaSession and mRemoteControlClient set?

Hi Erel. Thank you for your help.
In attachment you have file java. Anyway look this code (mMediaSession / mRemoteControlClient ):

B4X:
private MediaSession mMediaSession;
private RemoteControlClient mRemoteControlClient;
....
public void onCreate() {
        IntentFilter filter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
        this.mUserData = UserData.getInstance(getApplicationContext());
        this.receiver = new NetworkChangeReceiver();
        registerReceiver(this.receiver, filter);
        if (this.mAudioManager == null) {
            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) {
            Log.d("init()", "API " + VERSION.SDK_INT + " greater or equals " + 21);
            Log.d("init()", "Using MediaSession API.");
            this.mMediaSession = new MediaSession(this, "StreamPlayerServiceMediaSession");
            this.mMediaSession.setFlags(2);
            this.mMediaSession.setActive(true);
        }
    }
 

Attachments

  • StreamPlayerServiceExample.zip
    4.8 KB · Views: 371
Upvote 0

MarcoRome

Expert
Licensed User
Longtime User
Also this seem that work:

send track informations via A2DP/AVRCP

B4X:
private static final String AVRCP_PLAYSTATE_CHANGED = "com.android.music.playstatechanged";
private static final String AVRCP_META_CHANGED = "com.android.music.metachanged";

private void bluetoothNotifyChange(String what) {
    Intent i = new Intent(what);
    i.putExtra("id", Long.valueOf(getAudioId()));
    i.putExtra("artist", getArtistName());
    i.putExtra("album",getAlbumName());
    i.putExtra("track", getTrackName());
    i.putExtra("playing", isPlaying());       
    i.putExtra("ListSize", getQueue());
    i.putExtra("duration", duration());
    i.putExtra("position", position());
    sendBroadcast(i);
}
 
Upvote 0

MarcoRome

Expert
Licensed User
Longtime User
I found also this:

Example for sending text over AVRCP from an Android application.

B4X:
/**
* Generalized code from botifier, source code at https://github.com/grimpy/Botifier
* Provides example methods for sending text over AVRCP from an Android application.
* AVRCP is the Bluetooth protocol your phone uses to send song information to your car stereo/smartwatch.
* Only for Android 5.0+
*/

@Override
protected void onCreate(Bundle savedInstanceState) {
  //in activity or service
  mediaSession = new MediaSession(this, "YourAppName");
  audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
  setUpCallBack();
}

private void setUpCallBack() {
  //capture media events like play, stop
  //you don't actually use these callbacks
  //but you have to have this in order to pretend to be a media application
  mediaSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS |
          MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
  mediaSession.setCallback(new MediaSession.Callback() {
      @Override
      public void onPlay() {
          super.onPlay();
      }

      @Override
      public void onPause() {
          super.onPause();
      }

      @Override
      public void onSkipToNext() {
          super.onSkipToNext();
      }

      @Override
      public void onSkipToPrevious() {
          super.onSkipToPrevious();
      }

      @Override
      public void onStop() {
          super.onStop();
      }
  });
}

public void sendTextOverAVRCP() {
    PlaybackState state = new PlaybackState.Builder()
            .setActions(
                    PlaybackState.ACTION_PLAY | PlaybackState.ACTION_PLAY_PAUSE |
                            PlaybackState.ACTION_PLAY_FROM_MEDIA_ID | PlaybackState.ACTION_PAUSE |
                            PlaybackState.ACTION_SKIP_TO_NEXT | PlaybackState.ACTION_SKIP_TO_PREVIOUS)
            .setState(PlaybackState.STATE_PLAYING, 1, 1, SystemClock.elapsedRealtime())
            .build();
    //set the metadata to send, this is the text that will be displayed
    //if the strings are too long they might be cut off
    //you need to experiment with the receiving device to know max length
    MediaMetadata metadata = new MediaMetadata.Builder()
            .putString(MediaMetadata.METADATA_KEY_TITLE, "title")
            .putString(MediaMetadata.METADATA_KEY_ARTIST, "artist")
            .putString(MediaMetadata.METADATA_KEY_ALBUM_ARTIST, "album_artist")
            .putString(MediaMetadata.METADATA_KEY_ALBUM, "album")
            .putLong(MediaMetadata.METADATA_KEY_NUM_TRACKS, 123)
            .putLong(MediaMetadata.METADATA_KEY_DURATION, 456)
            .build();
    //setting this active makes the metadata you pass show up
    //other metadata from apps will not be shown
    mediaSession.setActive(true);
    mediaSession.setMetadata(metadata);
    mediaSession.setPlaybackState(state);

}

private void clearText() {
  //if you display text, calling this will stop displaying it
  //if there is another app which is using AVRCP,
  //control will be handed off that app
  if (mediaSession != null)
      mediaSession.setActive(false);
}
 
Upvote 0

MarcoRome

Expert
Licensed User
Longtime User
Also this seem that work:

send track informations via A2DP/AVRCP

B4X:
private static final String AVRCP_PLAYSTATE_CHANGED = "com.android.music.playstatechanged";
private static final String AVRCP_META_CHANGED = "com.android.music.metachanged";

private void bluetoothNotifyChange(String what) {
    Intent i = new Intent(what);
    i.putExtra("id", Long.valueOf(getAudioId()));
    i.putExtra("artist", getArtistName());
    i.putExtra("album",getAlbumName());
    i.putExtra("track", getTrackName());
    i.putExtra("playing", isPlaying());      
    i.putExtra("ListSize", getQueue());
    i.putExtra("duration", duration());
    i.putExtra("position", position());
    sendBroadcast(i);
}

I tried also this code:

Manifest:
B4X:
AddReceiverText(ssend, <intent-filter>
<action android:name="android.bluetooth.device.action.ACL_CONNECTED"/>
<action android:name="android.bluetooth.device.action.ACTION_ACL_DISCONNECTED"/>
</intent-filter>)
AddPermission(android.permission.BLUETOOTH)

In Service ssend:
B4X:
Sub Service_Start (StartingIntent As Intent)
Log(StartingIntent)
Log(StartingIntent.Action)

If StartingIntent.Action="android.bluetooth.device.action.ACL_CONNECTED" Then
CallSubDelayed(Main,"sendmessagebt")End If

End Sub

In Main
B4X:
Sub sendmessagebt
Dim i As Intent
i.Initialize("android.bluetooth.device.action.ACL_CONNECTED", "")
i.putExtra("artist", "Test");
Dim p As Phone
p.SendBroadcastIntent(i)
End Sub

But anyway dont work.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
This code compiles correctly:
B4X:
#AdditionalJar: com.android.support:support-v4
#AdditionalJar: com.android.support:mediarouter-v7
#AdditionalJar: com.google.android.gms:play-services-cast
Sub Process_Globals
End Sub

Sub Globals
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("1")
   Dim jo As JavaObject
   jo.InitializeContext
   jo.RunMethod("sendTrackInfoToBluetoothDevice", Null)
End Sub


Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub



#if JAVA
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMetadata;
import android.media.RemoteControlClient;
import android.media.RemoteControlClient.MetadataEditor;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.os.Binder;
import android.os.Build.VERSION;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.SystemClock;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.support.v7.media.MediaItemMetadata;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.format.Time;
import android.util.Log;
import android.content.Intent;
import android.content.IntentFilter;
import android.app.PendingIntent;
import android.app.Service;
import com.google.android.gms.cast.TextTrackStyle;
private AudioManager mAudioManager;
private AudioTrack mAudioTrack;
private RemoteControlClient mRemoteControlClient;
 private MediaSession mMediaSession;
    public void _onCreate() {
         BA.Log("Running onCreate");
    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) {
    Log.d("init()", "API " + VERSION.SDK_INT + " greater or equals " + 21);
    Log.d("init()", "Using MediaSession API.");
    this.mMediaSession = new MediaSession(this, "StreamPlayerServiceMediaSession");
    this.mMediaSession.setFlags(2);
    this.mMediaSession.setActive(true);
    }
    }
   public void sendTrackInfoToBluetoothDevice() {
  if (VERSION.SDK_INT >= 21) {
  this.mMediaSession.setMetadata(new MediaMetadata.Builder().putString(MediaItemMetadata.KEY_TITLE, "title").putString(MediaItemMetadata.KEY_ARTIST, "artist").putString(MediaMetadataCompat.METADATA_KEY_ALBUM, "album").build());
  this.mMediaSession.setPlaybackState(new PlaybackState.Builder().setActions(4).setState(3, -1, TextTrackStyle.DEFAULT_FONT_SCALE, SystemClock.elapsedRealtime()).build());
  } else if (VERSION.SDK_INT >= 18) {
  android.media.RemoteControlClient.MetadataEditor ed = this.mRemoteControlClient.editMetadata(true);
  ed.putString(7, "title");
  ed.putString(2, "artist");
  ed.putString(1, "playing title");
  ed.apply();
  this.mRemoteControlClient.setPlaybackState(3, -1, TextTrackStyle.DEFAULT_FONT_SCALE);
  }
  }
 
Upvote 0

MarcoRome

Expert
Licensed User
Longtime User
This code compiles correctly:
B4X:
#AdditionalJar: com.android.support:support-v4
#AdditionalJar: com.android.support:mediarouter-v7
#AdditionalJar: com.google.android.gms:play-services-cast
Sub Process_Globals
End Sub

Sub Globals
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("1")
   Dim jo As JavaObject
   jo.InitializeContext
   jo.RunMethod("sendTrackInfoToBluetoothDevice", Null)
End Sub


Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub



#if JAVA
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMetadata;
import android.media.RemoteControlClient;
import android.media.RemoteControlClient.MetadataEditor;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.os.Binder;
import android.os.Build.VERSION;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.SystemClock;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.support.v7.media.MediaItemMetadata;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.format.Time;
import android.util.Log;
import android.content.Intent;
import android.content.IntentFilter;
import android.app.PendingIntent;
import android.app.Service;
import com.google.android.gms.cast.TextTrackStyle;
private AudioManager mAudioManager;
private AudioTrack mAudioTrack;
private RemoteControlClient mRemoteControlClient;
private MediaSession mMediaSession;
    public void _onCreate() {
         BA.Log("Running onCreate");
    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) {
    Log.d("init()", "API " + VERSION.SDK_INT + " greater or equals " + 21);
    Log.d("init()", "Using MediaSession API.");
    this.mMediaSession = new MediaSession(this, "StreamPlayerServiceMediaSession");
    this.mMediaSession.setFlags(2);
    this.mMediaSession.setActive(true);
    }
    }
   public void sendTrackInfoToBluetoothDevice() {
  if (VERSION.SDK_INT >= 21) {
  this.mMediaSession.setMetadata(new MediaMetadata.Builder().putString(MediaItemMetadata.KEY_TITLE, "title").putString(MediaItemMetadata.KEY_ARTIST, "artist").putString(MediaMetadataCompat.METADATA_KEY_ALBUM, "album").build());
  this.mMediaSession.setPlaybackState(new PlaybackState.Builder().setActions(4).setState(3, -1, TextTrackStyle.DEFAULT_FONT_SCALE, SystemClock.elapsedRealtime()).build());
  } else if (VERSION.SDK_INT >= 18) {
  android.media.RemoteControlClient.MetadataEditor ed = this.mRemoteControlClient.editMetadata(true);
  ed.putString(7, "title");
  ed.putString(2, "artist");
  ed.putString(1, "playing title");
  ed.apply();
  this.mRemoteControlClient.setPlaybackState(3, -1, TextTrackStyle.DEFAULT_FONT_SCALE);
  }
  }

Erel work very well.
So also problem with A2DP is vanish.
Thank you very much
 
Upvote 0

Robert Valentino

Well-Known Member
Licensed User
Longtime User
This code compiles correctly:
B4X:
#AdditionalJar: com.android.support:support-v4
#AdditionalJar: com.android.support:mediarouter-v7
#AdditionalJar: com.google.android.gms:play-services-cast
Sub Process_Globals
End Sub

Sub Globals
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("1")
   Dim jo As JavaObject
   jo.InitializeContext
   jo.RunMethod("sendTrackInfoToBluetoothDevice", Null)
End Sub


Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub



#if JAVA
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMetadata;
import android.media.RemoteControlClient;
import android.media.RemoteControlClient.MetadataEditor;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.os.Binder;
import android.os.Build.VERSION;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.SystemClock;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.support.v7.media.MediaItemMetadata;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.format.Time;
import android.util.Log;
import android.content.Intent;
import android.content.IntentFilter;
import android.app.PendingIntent;
import android.app.Service;
import com.google.android.gms.cast.TextTrackStyle;
private AudioManager mAudioManager;
private AudioTrack mAudioTrack;
private RemoteControlClient mRemoteControlClient;
private MediaSession mMediaSession;
    public void _onCreate() {
         BA.Log("Running onCreate");
    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) {
    Log.d("init()", "API " + VERSION.SDK_INT + " greater or equals " + 21);
    Log.d("init()", "Using MediaSession API.");
    this.mMediaSession = new MediaSession(this, "StreamPlayerServiceMediaSession");
    this.mMediaSession.setFlags(2);
    this.mMediaSession.setActive(true);
    }
    }
   public void sendTrackInfoToBluetoothDevice() {
  if (VERSION.SDK_INT >= 21) {
  this.mMediaSession.setMetadata(new MediaMetadata.Builder().putString(MediaItemMetadata.KEY_TITLE, "title").putString(MediaItemMetadata.KEY_ARTIST, "artist").putString(MediaMetadataCompat.METADATA_KEY_ALBUM, "album").build());
  this.mMediaSession.setPlaybackState(new PlaybackState.Builder().setActions(4).setState(3, -1, TextTrackStyle.DEFAULT_FONT_SCALE, SystemClock.elapsedRealtime()).build());
  } else if (VERSION.SDK_INT >= 18) {
  android.media.RemoteControlClient.MetadataEditor ed = this.mRemoteControlClient.editMetadata(true);
  ed.putString(7, "title");
  ed.putString(2, "artist");
  ed.putString(1, "playing title");
  ed.apply();
  this.mRemoteControlClient.setPlaybackState(3, -1, TextTrackStyle.DEFAULT_FONT_SCALE);
  }
  }

This code gives the following: -Xlint:Deprecation

How do I express Deprecation to the compiler?
 

Attachments

  • Deprecation.png
    Deprecation.png
    15.3 KB · Views: 358
Upvote 0
Top