I'm trying to create a new android application that is comprised of multiple mini-games. The launcher activity extends BaseGameActivity and has a sign-in button and a ListView containing all the possible games that can be played.
Inside of a mini-game activity (also extends BaseGameActivity), how can I get it to create a notification which will launch a specific Activity? Currently, when I call invitePlayersToGame, the invitation that gets sent is for the full application (Mini-Games) and not the individual game (specific dice game).
public void invitePlayersToGame(View pView) {
Intent intent = Games.RealTimeMultiplayer.getSelectOpponentsIntent(getApiClient(), 1, 1);
intent.putExtra("gameName", "Patman Yahtzee");
startActivityForResult(intent, RC_SELECT_PLAYERS);
}
Is there a way to get the notification to generate with a specific message? Is there a way to get notification to open directly to the mini-game activity without going to the main launcher activity first?
Any help is appreciated. Thanks!
You can send sendReliableMessage for method handshaking.
First enter a room (quickgame or send invite).
public void openInvitationIntent() {
// launch the player selection screen
// minimum: 1 other player; maximum: 1 other players
Intent intent = Games.RealTimeMultiplayer.getSelectOpponentsIntent(mGoogleApiClient, 1, 1);
startActivityForResult(intent, RC_SELECT_PLAYERS);
}
onConnected:
#Override
public void onConnected(Bundle connectionHint) {
// QuickGame
if (mGameMode == 1) {
Log.d(TAG, "onConnected() called. Sign in successful!");
Log.d(TAG, "Sign-in succeeded.");
startQuickGame();
// register listener so we are notified if we receive an invitation to play
// while we are in the game
if (connectionHint != null) {
Log.d(TAG, "onConnected: connection hint provided. Checking for invite.");
Invitation inv = connectionHint.getParcelable(Multiplayer.EXTRA_INVITATION);
if (inv != null && inv.getInvitationId() != null) {
// retrieve and cache the invitation ID
Log.d(TAG, "onConnected: connection hint has a room invite!");
acceptInviteToRoom(inv.getInvitationId());
return;
}
}
}
// Send request
else if (mGameMode == 0) {
// request code for the "select players" UI
// can be any number as long as it's unique
invitationInbox();
}
// request accepted
else {
mIncomingInvitationId = getIntent().getExtras().getString(AppConstants.RC_INVITATION_ID);
RoomConfig.Builder roomConfigBuilder = makeBasicRoomConfigBuilder();
roomConfigBuilder.setInvitationIdToAccept(mIncomingInvitationId);
Games.RealTimeMultiplayer.join(mGoogleApiClient, roomConfigBuilder.build());
// prevent screen from sleeping during handshake
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
}
After this, you can send model class (includes what you need).
private void broadcastMessage(ModelGameRecievedMessage broadcastedMessage, boolean isFinal) {
try {
if ( mParticipants != null && broadcastedMessage != null) {
byte[] bytes = Utils.serialize(broadcastedMessage);
// Send to every other participant.
for (Participant p : mParticipants) {
if (p.getParticipantId().equals(mMyId)) {
continue;
}
if (p.getStatus() != Participant.STATUS_JOINED) {
continue;
}
if (mRoomId != null) {
if (isFinal) {
// final score notification must be sent via reliable broadcastedMessage
Games.RealTimeMultiplayer.sendReliableMessage(mGoogleApiClient, null, bytes,
mRoomId, p.getParticipantId());
} else {
// it's an interim score notification, so we can use unreliable
Games.RealTimeMultiplayer.sendUnreliableMessage(mGoogleApiClient, bytes,
mRoomId, p.getParticipantId());
}
}
}
Logy.l("broadcastedMessage.getMessageTypeId(); " + broadcastedMessage.getMessageTypeId());
Logy.l("broadcastedMessage.getMessage(); " + broadcastedMessage.getMessage());
}
} catch (IOException e) {
e.printStackTrace();
}
}
finally you can reach the data on other devices:
#Override
public void onRealTimeMessageReceived(RealTimeMessage rtm) {
byte[] bufy = rtm.getMessageData();
ModelGameRecievedMessage recievedMessage = null;
try {
recievedMessage = (ModelGameRecievedMessage) Utils.deserialize(bufy);
Logy.l("recievedMessage.getMessageTypeId(); " + recievedMessage.getMessageTypeId());
Logy.l("recievedMessage.getMessage(); " + recievedMessage.getMessage());
} catch (Exception e) {
Logy.e("Exception onRealTimeMessageReceived deserialize: " + e);
}
switch (recievedMessage.getMessageTypeId()) {
case AppConstants.RC_MULTI_START_TIMEMILIS_MULTIPLAYER:
....
Related
In my application i should used socket.io and i want when receive my event update UI elements!
I write below codes and i receive my events show me logs, but not update any UI!
I want when receive event, check this winner is user or not and then update my UI.
In logCat show me my logs but not update any UI elements!
My codes:
public void onsocketFinishRecieve(final JSONObject ob) {
try {
((BaseActivity) context).runOnUiThread(() -> {
try {
cancelTimer();
final FinishResponse finishResponse = new Gson().fromJson(ob.toString(), FinishResponse.class);
if (finishResponse.getRes().getWinnerName().equals("not user") || finishResponse.getRes().getWinnerName().equals("not winner")) {
winnerNameWhenFinished = "Not winner";
} else {
winnerNameWhenFinished = finishResponse.getRes().getWinnerName();
}
if (detail.getId() != null) {
if (detail.getId() == finishResponse.getRes().getId()) {
//Set new winner layouts
//Register in auction
if (Constants.profileResponse != null) {
if (Constants.profileResponse.getRes() != null) {
if (Constants.profileResponse.getRes().getUser() != null) {
//Winner
if (Constants.profileResponse.getRes().getUser().getId().equals(finishResponse.getRes().getUserId())) {
Log.e("FinishedSocket", "1");
detailPage_bottomWinnerRateTxt.setVisibility(View.GONE);
detailPage_bottomWinnerBuyTxt.setText("Show basket");
detailPage_bottomWinnerBuyTxt.setOnClickListener(v -> {
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra("OPEN_CART_IN_MAIN", "true");
startActivity(intent);
});
} else {
Log.e("FinishedSocket", "2");
//Loser
detailPage_bottomWinnerBuyTxt.setText("Awesome offers");
}
}
}
}
}
}
} catch (Exception e) {
Log.e("DetailResErr", e.getMessage());
}
});
} catch (Exception e) {
Log.e("DetailResErr", e.getMessage());
}
}
Logcat message :
2020-03-08 13:37:37.399 E/FinishedSocket: 2
In logcat show me above message , why not run this line : detailPage_bottomWinnerBuyTxt.setText("Awesome offers"); ??
How can i fix it?
try to run this on Mainthread like this.
someActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
//Your code to run in GUI thread here
detailPage_bottomWinnerBuyTxt.setText("Awesome offers");
}
});
Sockets work on IOThread while other side UI Work on separate Thread called UI thread. So, update the UI element on UI Thread.
Use Annotation :
#UiThread
public abstract void setText(#NonNull String text) { ... }
For know about more annotation, Check the following blog:
https://medium.com/#gurwindersingh_37022/android-annotations-30b4a2850d0
I am developing an android Music Player application .I just want to pause when a call arrives , that has been acheived by the use of Telephony Manager , but i also wants to detect the Whatsapp calls and other internet calls .How to make that possible
This is my code what changes should be done to detect the internet calls also to pause the player on call and play on call ended
private void player_manager_on_call() {
// TODO Auto-generated method stub
// Manage player on Call
phoneStateListener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if (state == TelephonyManager.CALL_STATE_RINGING)
// Incoming // call: // Pause // music
{
try {
boolean is_playing = mediaController.Check_IsPlaying();
if (is_playing) {
Log.d("xiomi", "CALL_STATE_RINGING");
// Get details of song from sp
position = PlayerConstants.SONG_NUMBER;
data = PlayerConstants.SONGS_LIST.get(position);
Play_link = data.getPath();
Artist = data.getArtist() + "-" + data.getAlbum();
albumArt = UtilFunctions.getAlbumart(
getApplicationContext(), data.getAlbumId());
Log.e("albumArt", "albumArt " + albumArt);
mediaController.doPauseResume();
showControls();
// start notification service again for play
startNotificationService(MainActivity.this,
data.getTitle(), Artist, albumArt,
is_playing, position);
}
} catch (Exception e) { // TODO Auto-generated catch block
e.printStackTrace();
}
} else if (state == TelephonyManager.CALL_STATE_IDLE) // Not in
// //call:
// //
// Play
// //
// music
try {
if (player != null) {
Log.d("xiomi", "CALL_STATE_RINGING");
// Get details of song from sp
position = PlayerConstants.SONG_NUMBER;
data = PlayerConstants.SONGS_LIST.get(position);
Play_link = data.getPath();
Artist = data.getArtist() + "-" + data.getAlbum();
albumArt = UtilFunctions.getAlbumart(
getApplicationContext(), data.getAlbumId());
Log.e("albumArt", "albumArt " + albumArt);
boolean is_playing = mediaController
.Check_IsPlaying();
mediaController.doPauseResume();
showControls();
// start notification service again for play
startNotificationService(MainActivity.this,
data.getTitle(), Artist, albumArt,
is_playing, position);
}
} catch (Exception e) { // TODO Auto-generated catch block
e.printStackTrace();
}
else if (state == TelephonyManager.CALL_STATE_OFFHOOK) // A //
// call
// is // dialing, // active // or // on // hold
{
try {
boolean is_playing = mediaController.Check_IsPlaying();
if (is_playing) {
Log.d("xiomi", "CALL_STATE_OFFHOOK");
// Get details of song from sp
position = PlayerConstants.SONG_NUMBER;
data = PlayerConstants.SONGS_LIST.get(position);
Play_link = data.getPath();
Artist = data.getArtist() + "-" + data.getAlbum();
albumArt = UtilFunctions.getAlbumart(
getApplicationContext(), data.getAlbumId());
Log.e("albumArt", "albumArt " + albumArt);
mediaController.doPauseResume();
showControls();
// start notification service again for play
startNotificationService(MainActivity.this,
data.getTitle(), Artist, albumArt,
is_playing, position);
}
} catch (Exception e) { // TODO Auto-generated catch block
e.printStackTrace();
}
}
super.onCallStateChanged(state, incomingNumber);
}
};
TelephonyManager mgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
if (mgr != null) {
mgr.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
}
I'll avoid coping code from Android documentation so i'll just give you links which should answer your question.
First you don't need to detect calls from different apps by yourself, you just need to register broadcast receiver and act on audio focus changes.
Here you can check it out how to handle when headphones are disconnected:
https://developer.android.com/guide/topics/media-apps/volume-and-earphones.html
And on link below you can see answer on your question how to handle calls and etc.
https://developer.android.com/guide/topics/media-apps/audio-focus.html
Is this right way of doing? AM using this samples https://altbeacon.github.io/android-beacon-library/samples.html
public class App extends Application
implements BootstrapNotifier, BeaconConsumer, RangeNotifier {
private final String TAG = "Application ";
protected static final Region beaconRegion = new Region("2f234454-cf6d-4a0f-adf2-f4911ba9ffa6", null, null, null);
protected BeaconManager beaconManager = null;
private RegionBootstrap regionBootstrap;
private BackgroundPowerSaver backgroundPowerSaver;
protected static String sLog = "";
#Override
public void onCreate() {
super.onCreate();
logIt(TAG, beaconRegion.getId1()+"onCreate - In"+beaconRegion.getUniqueId());
beaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().clear();
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));//iBeacon (tutti)
//--- wake up the app when a beacon is seen
regionBootstrap = new RegionBootstrap(this, beaconRegion);
//--- activate power saver
backgroundPowerSaver = new BackgroundPowerSaver(this);
beaconManager.bind(this);
logIt(TAG, "onCreate - Out");
}
private void logIt (String TAG, String msg) {
sLog += TAG + msg + "\n";
Log.w(TAG, msg);
}
//-------------------------//
//--- BootstrapNotifier ---//
//-------------------------//
#Override
public void didDetermineStateForRegion(int state, Region region) {
String msg = "didDetermineStateForRegion ";
switch(state) {
case MonitorNotifier.INSIDE:
msg +="(INSIDE)";
break;
case MonitorNotifier.OUTSIDE:
msg +="(OUTSIDE)";
break;
default:
msg +="(state=" +state +")";
break;
}
logIt(TAG, msg);
}
#Override
public void didEnterRegion(Region arg0) {
logIt(TAG, "didEnterRegion - In");
try {
beaconManager.startRangingBeaconsInRegion(beaconRegion);
logIt(TAG,"dER - startRangingBeaconsInRegion OK");
} catch (RemoteException e) {
logIt(TAG, "dER - startRangingBeaconsInRegion Err " +e);
}
logIt(TAG, "didEnterRegion - Out");
}
#Override
public void didExitRegion(Region region) {
logIt(TAG, "didExitRegion - In");
try {
beaconManager.stopRangingBeaconsInRegion(beaconRegion);
logIt(TAG,"dXR - stopRangingBeaconsInRegion OK");
} catch (RemoteException e) {
logIt(TAG, "dXR - stopRangingBeaconsInRegion Err " +e);
}
logIt(TAG, "didExitRegion - Out");
}
//----------------------//
//--- BeaconConsumer ---//
//----------------------//
#Override
public void onBeaconServiceConnect() {
logIt(TAG, "onBeaconServiceConnect - In");
beaconManager.setRangeNotifier(this);
logIt(TAG, "onBeaconServiceConnect - Out");
}
//---------------------//
//--- RangeNotifier ---//
//---------------------//
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
logIt(TAG, "didRangeBeaconsInRegion - " +beacons.size() +" beacons");
Toast.makeText(getApplicationContext(), beaconRegion.getId1()+" beacon detected "+beacons.size(),
Toast.LENGTH_SHORT).show();
for(Beacon beac: beacons)
{
System.out.println(beac.getId1()+"id 1"+TAG);
if(beac.getId1().equals("2f234454-cf6d-4a0f-adf2-f4911ba9ffa6")/send notification
}
}
}
So Basically that class, which extends application am listening to beacons around. Below, is how am turning my phone into a beacon.I am doing this inside an activity on click of button. So there is two phones with app downloaded on both, once he clicks on one app the button I want the other phone to detect it since i have implemented in extends application class.
the turn ur android to beacon code.
Beacon beacon = new Beacon.Builder()
.setId1("2f234454-cf6d-4a0f-adf2-f4911ba9ffa6") // UUID for beacon
.setId2("1") // Major for beacon
.setId3("5") // Minor for beacon
.setManufacturer(0x004C) // Radius Networks.0x0118 Change this for other beacon layouts//0x004C for iPhone
.setTxPower(-56) // Power in dB
.setDataFields(Arrays.asList(new Long[]{0l})) // Remove this for beacon layouts without d: fields
.build();
BeaconParser beaconParser = new BeaconParser()
.setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24");
beaconTransmitter = new BeaconTransmitter(MenuActivity.this, beaconParser);
beaconTransmitter.startAdvertising(beacon, new AdvertiseCallback() {
#Override
public void onStartFailure(int errorCode) {
Log.e("tag", "Advertisement start failed with code: " + errorCode);
}
#Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
Log.i("tag", "Advertisement start succeeded.");
Toast.makeText(MenuActivity.this, "advertisement start succeeded",
Toast.LENGTH_SHORT).show();
System.out.println("startedddddddddddd");
}
});
// beaconTransmitter.stopAdvertising();
}
catch(Exception o)
{
System.out.println("affda "+o.getMessage());
}
I am also havig an issue, that didenterregion and didRangeBeaconsInRegion are fired many times, so am sending many notification to the user multiple times. its not user friendly.
The didRangeBeaconsInRegion callback is supposed to get called many times -- that's how ranging works. It is called approximately once per second when the beacon is detected to tell you it is there and give you a distance estimate.
If you want to fire a notification only once for the first time you get a call to this method, then you can set a flag for this specific beacon.
Here is an example of some code you might use to do that:
// Add this to the top of your class
private HashMap<String,Boolean> mAlreadySentNotification = new HashMap<String,Boolean>();
...
// Add this to the inside of your didRangeBeaconsInRegion method
if (mAlreadySentNotification.get(beacon.toString())) {
mAlreadySentNotification.put(beacon.toString(), true);
// Send notification here.
}
I followed these instructions to integrate both Libgdx and native android code using ActionResolver interface. I have no problem calling the Android method from the Libgdx part of my code. But I am hitting a dead end when I am trying to intergrate Google IAP with Libgdx. According to TrivialDrive example, it uses mPurchaseFinishedListener (outside of calling method).
My question is: how do I pass this IAP resultcode back to Libgdx since the listener is outside the calling method? Currently, purchase process went through, but the libgdx part of my code is not being "informed" of the purchase status/result.
This is my code:
Any help is much appreciated.
ActionResolver:
public interface IActionResolver {
public int requestIabPurchase(int product);
}
MainActivity:
public class MainActivity extends AndroidApplication implements IActionResolver {
// Debug tag, for logging
static final String TAG = "greatgame";
// Does the user have the premium upgrade?
boolean mIsUpgraded = false;
// SKUs for our products: the cat, all, or pow
static final String SKU_UPGRADE = "android.test.purchased";
// (arbitrary) request code for the purchase flow
static final int RC_REQUEST = 10001;
// The helper object
IabHelper mHelper;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
cfg.useGL20 = false;
initialize(new Catland(this), cfg);
}
void iAbStartup() {
String base64EncodedPublicKey = "some key";
// Create the helper, passing it our context and the public key to verify signatures with
Log.d(TAG, "Creating IAB helper.");
mHelper = new IabHelper(this, base64EncodedPublicKey);
// enable debug logging (for a production application, you should set this to false).
mHelper.enableDebugLogging(true);
// Start setup. This is asynchronous and the specified listener
// will be called once setup completes.
Log.d(TAG, "Starting setup.");
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
Log.d(TAG, "Setup finished.");
if (!result.isSuccess()) {
// Oh noes, there was a problem.
Log.d(TAG, "Problem setting up in-app billing: " + result);
return;
}
// Have we been disposed of in the meantime? If so, quit.
if (mHelper == null) {
return;
}
// IAB is fully set up. Now, let's get an inventory of stuff we own.
Log.d(TAG, "Setup successful. Querying inventory.");
mHelper.queryInventoryAsync(mGotInventoryListener);
}
});
}
// Listener that's called when we finish querying the items and subscriptions we own
IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
Log.d(TAG, "Query inventory finished.");
// Have we been disposed of in the meantime? If so, quit.
if (mHelper == null) {
return;
}
// Is it a failure?
if (result.isFailure()) {
Log.d(TAG, "Failed to query inventory: " + result);
return;
}
Log.d(TAG, "Query inventory was successful.");
// Do we have the SKU_UPGRADE upgrade?
Purchase thisUpgrade = inventory.getPurchase(SKU_UPGRADE);
mIsUpgraded = (thisUpgrade != null && verifyDeveloperPayload(thisUpgrade));
Log.d(TAG, "User is " + (mIsUpgraded ? "Upgraded" : "Free"));
Log.d(TAG, "Initial inventory query finished; enabling main UI.");
runPurchaseFlow(submitProduct);
}
};
// Run real purchase flow
public void runPurchaseFlow(int product) {
Log.d(TAG, "runPurchaseFlow");
/* TODO: for security, generate your payload here for verification. See the comments on
* verifyDeveloperPayload() for more info. Since this is a SAMPLE, we just use
* an empty string, but on a production app you should carefully generate this. */
String payload = "";
if (product == 1)
mHelper.launchPurchaseFlow(this, SKU_UPGRADE, RC_REQUEST, mPurchaseFinishedListener, payload);
}
// Callback for when a purchase is finished
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
Log.d(TAG, "Purchase finished: " + result + ", purchase: " + purchase);
// if we were disposed of in the meantime, quit.
if (mHelper == null) return;
if (result.isFailure()) {
Log.d(TAG, "Error purchasing: " + result);
return;
}
if (!verifyDeveloperPayload(purchase)) {
Log.d(TAG, "Error purchasing. Authenticity verification failed.");
return;
}
Log.d(TAG, "Purchase successful.");
if (purchase.getSku().equals(SKU_CAT)) {
// bought the upgrade!
Log.d(TAG, "Purchase Upgrade. Congratulating user.");
mIsUpgraded = true;
// how do i pass this result to the libgdx?
}
}
};
/** Verifies the developer payload of a purchase. */
boolean verifyDeveloperPayload(Purchase p) {
String payload = p.getDeveloperPayload();
return true;
}
#Override
public int requestIabPurchase(int product) {
iAbStartup();
return 0; // how do i get the result from mPurchaseFinishedListener?
}
}
PurchaseScreen
result = greatgame.actionResolver.requestIabPurchase(1);
You won't be able to return the result from requestIabPurchase() - the only methods of doing so would block for a long time. The best way, in my opinion, would be to create a listener interface of your own that your LibGdx project implements, and pass that into your request interface. For example:
In your libGdx project somewhere:
interface PurchaseCallback {
public int setPurchaseResult(int result);
}
ActionResolver:
public interface IActionResolver {
public int requestIabPurchase(int product, PurchaseCallback callback);
}
In PurchaseScreen, implement PurchaseCallback:
#override
public int setPurchaseResult(int result) {
// Yay! I have a result from a purchase! Maybe you want a boolean instead of an int? I don't know. Maybe an int (for the product code) and a boolean.
}
...and pass whatever is implementing PurchaseCallback (I'm assuming your PurchaseScreen does itself):
result = greatgame.actionResolver.requestIabPurchase(1, this);
Finally, hook it all up in MainActivity:
PurchaseCallback mCallback = null;
mPurchaseFinishedListener = ... etc. etc.
.
.
.
if (mCallback != null) {
mCallback.setPurchaseResult(0);
}
.
.
.
#Override
public int requestIabPurchase(int product, PurchaseCallback callback) {
mCallback = callback; // save this for later
iAbStartup();
return 0;
}
Note that you should call PurchaseCallback.setPurchaseResult() everywhere that mPurchaseFinishedListener has return, not only at the line // how do i pass this result to the libgdx? - otherwise, you will never know if a purchase failed or is just taking a really long time.
I have a CC2540 BLE kit and i want to see the battery level of the kit in my smartphone app. I have made the code, which gets the battery level from the kit. The battery level is called BodySensor in this case:
First, i will go into the characteristic value of the battery service part for the kit. So i use the Service and Characteristic UUID's for the battery service:
public void getBodySensorLoc(BluetoothDevice device)
{
Log.i(TAG, "getBodySensorLoc");
BluetoothGattService mHRP = mBluetoothGatt.getService(device, HRP_SERVICE);
if (mHRP == null)
{
Log.e(TAG, "getBodySensorLoc: mHRP = null");
return;
}
BluetoothGattCharacteristic mBSLcharac = mHRP.getCharacteristic(BODY_SENSOR_LOCATION);
if (mBSLcharac == null) {
Log.e(TAG, "getBodySensorLoc: mBSLcharac = null");
return;
}
mBluetoothGatt.readCharacteristic(mBSLcharac);
}
My purpose is to read the battery level, when pressing a button in my application. So i implement this button in my Activity class:
((Button) findViewById(R.id.btn_BSL)).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
mService.getBodySensorLoc(mDevice);
}
});
This kit will automatically send the battery level back to the smartphone. So i will set focus on onCharacteristicRead method of BluetoothGattCallback part in my code:
private BluetoothGattCallback mGattCallbacks = new BluetoothGattCallback()
{
public void onCharacteristicRead(BluetoothGattCharacteristic charac, int status)
{
UUID charUuid = charac.getUuid();
Bundle mBundle = new Bundle();
Message msg = Message.obtain(mActivityHandler, HRP_VALUE_MSG);
Log.i(TAG, "onCharacteristicRead");
if (charUuid.equals(BODY_SENSOR_LOCATION))
mBundle.putByteArray(BSL_VALUE, charac.getValue());
msg.setData(mBundle);
msg.sendToTarget();
}
};
I want the application to show the received battery level in a textview. The kit sends the battery level as a integer, so if the level is 70%, it sends "70". The code includes a Handler in the Activity class:
private Handler mHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
switch (msg.what)
{
case HRPService.HRP_VALUE_MSG:
Log.d(TAG, "mHandler.HRP_VALUE_MSG");
Bundle data1 = msg.getData();
final byte[] bslval = data1.getByteArray(HRPService.BSL_VALUE);
runOnUiThread(new Runnable()
{
public void run()
{
if (bslval != null)
{
try {
Log.i(TAG, "BYTE BSL VAL =" + bslval[0]);
TextView bsltv = (TextView) findViewById(R.id.BodySensorLocation);
bsltv.setText("\t" + mContext.getString(R.string.BodySensorLocation)
+ getBodySensorLocation(bslval[0]));
} catch (Exception e)
{
Log.e(TAG, e.toString());
}
}
}
});
default:
super.handleMessage(msg);
}
}
};
The problem is that the textview doesn't show anything, when i press this button in my application after i connected my smartphone with the kit. Can anyone tell me, where the problem is ?.
Thanks in advance
Unsure what exact kit you have. Unsure if they all have battery level measuring hardware on board. Maybe this is the reason.