I want to implement the Online/Offline/IsTying functionality using the pubnub library in android. For this i created the Pubnub connection.
//create the pubnub connection
PNConfiguration configuration = new PNConfiguration();
configuration.setPublishKey(PUBNUB_PUBLISH_KEY);
configuration.setSubscribeKey(PUBNUB_SUBSCRIBE_KEY);
configuration.setLogVerbosity(PNLogVerbosity.BODY);
configuration.setConnectTimeout(100000);
configuration.setSubscribeTimeout(31000);
configuration.setHeartbeatNotificationOptions(PNHeartbeatNotificationOptions.ALL);
configuration.setPresenceTimeoutWithCustomInterval(120,59);
configuration.setPresenceTimeout(120);
mPubNub = new PubNub(configuration);
And after that i set the subscriber callback to the listener
**strong text**
private SubscribeCallback subscribeCallback = new SubscribeCallback() {
#Override
public void status(PubNub pubnub, PNStatus status) {
Log.d("Chat", "status() called with: pubnub = [" + pubnub + "], status = [" + status + "]");
if (status.getOperation() != null) {
switch (status.getOperation()) {
// let's combine unsubscribe and subscribe handling for ease of use
case PNSubscribeOperation:
case PNUnsubscribeOperation:
Toast.makeText(ChatAppService.this, "Status : " + status.getOperation().name(), Toast.LENGTH_SHORT).show();
// note: subscribe statuses never have traditional
// errors, they just have categories to represent the
// different issues or successes that occur as part of subscribe
switch (status.getCategory()) {
case PNConnectedCategory:
// this is expected for a subscribe, this means there is no error or issue whatsoever
Toast.makeText(ChatAppService.this, "Status : " + status.getCategory(), Toast.LENGTH_SHORT).show();
break;
case PNReconnectedCategory:
// this usually occurs if subscribe temporarily fails but reconnects. This means
// there was an error but there is no longer any issue
Toast.makeText(ChatAppService.this, "Status : " + status.getCategory(), Toast.LENGTH_SHORT).show();
HashMap<String,String> map = new HashMap();
map.put("State","Online");
pubnub.setPresenceState().channels(Arrays.asList(Constants.GLOBAL_CHANNEL)).state(map).uuid(pubnub.getConfiguration().getUuid());
break;
case PNDisconnectedCategory:
// this is the expected category for an unsubscribe. This means there
// was no error in unsubscribing from everything
Toast.makeText(ChatAppService.this, "Status : " + status.getCategory(), Toast.LENGTH_SHORT).show();
HashMap<String,String> mapOffline = new HashMap();
mapOffline.put("State","Offline");
pubnub.setPresenceState().channels(Arrays.asList(Constants.GLOBAL_CHANNEL)).state(mapOffline).uuid(pubnub.getConfiguration().getUuid());
break;
case PNTimeoutCategory:
HashMap<String,String> mapTimeout = new HashMap();
mapTimeout.put("State","Offline");
pubnub.setPresenceState().channels(Arrays.asList(Constants.GLOBAL_CHANNEL)).state(mapTimeout).uuid(pubnub.getConfiguration().getUuid());
pubnub.reconnect();
break;
case PNUnexpectedDisconnectCategory:
// this is usually an issue with the internet connection, this is an error, handle appropriately
Toast.makeText(ChatAppService.this, "Status : " + status.getCategory(), Toast.LENGTH_SHORT).show();
pubnub.reconnect();
break;
case PNAccessDeniedCategory:
// this means that PAM does allow this client to subscribe to this
// channel and channel group configuration. This is another explicit error
Toast.makeText(ChatAppService.this, "Status : " + status.getCategory(), Toast.LENGTH_SHORT).show();
break;
default:
// More errors can be directly specified by creating explicit cases for other
// error categories of `PNStatusCategory` such as `PNTimeoutCategory` or `PNMalformedFilterExpressionCategory` or `PNDecryptionErrorCategory`
}
break;
case PNHeartbeatOperation:
// heartbeat operations can in fact have errors, so it is important to check first for an error.
// For more information on how to configure heartbeat notifications through the status
// PNObjectEventListener callback, consult <link to the PNCONFIGURATION heartbeart config>
if (status.isError()) {
// There was an error with the heartbeat operation, handle here
} else {
// heartbeat operation was successful
}
break;
default: {
// Encountered unknown status type
}
}
} else {
// After a reconnection see status.getCategory()
}
}
#Override
public void message(PubNub pubnub, PNMessageResult message) {
//TODO: If App open: Save to database and broadcast for database change else show Notification
}
#Override
public void presence(PubNub pubnub, PNPresenceEventResult presence) {
Log.d("chat", "presence() called with: pubnub = [" + pubnub + "], presence = [" + presence + "]");
}
};`
Finally the issue is that when i leave the group then no presence callback is coming.I should get the event of leave the channel with user state so that i can remove the user from the online user's list.
for unsubscribing the group
pubnub.unsubscribe().channels(Arrays.asList(channel)).execute()
when i subscribe the channel then presence callback calls three time
1. event : join
2. event : state-changes
3. event : leave
I am not getting how to handle this scenario in Android. Please help me i am stucking in this problem from last three days.
Related
sendbox send a request but not retrieve the user data in this method
public void onUserDataResponse(UserDataResponse userDataResponse) {
final UserDataResponse.RequestStatus status = userDataResponse.getRequestStatus();
switch (status) {
case SUCCESSFUL:
currentUserId = userDataResponse.getUserData().getUserId();
currentMarketplace = userDataResponse.getUserData().getMarketplace();
break;
case FAILED:
Log.d("TAG", "onUserDataResponse: " + new Exception().getMessage());
case NOT_SUPPORTED:
// Fail gracefully.
Log.d("TAG", "onUserDataResponse: "+ new Exception().getMessage());
break;
}
}
I'm using RxAndroidBle 2 to watch a characteristic for CSC but I cannot read some characteristics before. It's also the first time I'm using ReactiveX so I have to deal with flatMap, flatMapSingle, etc.
Here's my code to register a handler for watching CSC Measure:
connectionSubscription = device.establishConnection(false)
// Register for notifications on CSC Measure
.flatMap(rxBleConnection -> rxBleConnection.setupNotification(Constants.CSC_MEASURE))
.doOnNext(notificationObservable -> {
// Notification has been set up
Log.d(TAG, "doOnNext = " + notificationObservable.toString());
})
.flatMap(notificationObservable -> {
Log.d(TAG, "flatMap = " + notificationObservable);
return notificationObservable;
}) // <-- Notification has been set up, now observe value changes.
.subscribe(
this::onCharacteristicChanged,
throwable -> {
if (throwable instanceof BleDisconnectedException) {
Log.e(TAG, "getCanonicalName = " + throwable.getClass().getCanonicalName());
}
}
);
And then the code for extracting the value:
private void onCharacteristicChanged(byte[] bytes) {
Integer f = ValueInterpreter.getIntValue(bytes, ValueInterpreter.FORMAT_UINT8, 0);
Log.d(TAG, "flags " + f);
switch (f) {
case 0: // 0x00000000 is not authorized
Log.w(TAG, "flags cannot be properly detected for this CSC device");
break;
case 1:
// sensor is in speed mode (mounted on the rear wheel)
// Cumulative Wheel Revolutions
Integer sumWheelRevs = ValueInterpreter.getIntValue(bytes, ValueInterpreter.FORMAT_UINT32, 1);
// Last Wheel event time
Integer lastWheelEvent = ValueInterpreter.getIntValue(bytes, ValueInterpreter.FORMAT_UINT16, 5);
Log.d(TAG, "Last wheel event detected at " + lastWheelEvent + ", wheel revs = " + sumWheelRevs);
break;
case 2:
// sensor is in cadence mode (mounted on the crank)
// Last Crank Event Time
// Cumulative Crank Revolutions
break;
}
}
I have another piece of working code to read ONE characteristic, but how can I process a list of characteristics?
.flatMapSingle(rxBleConnection -> rxBleConnection.readCharacteristic(Constants.DEVICE_HARDWARE))
.subscribe(
characteristicValue -> {
String deviceHardware = ValueInterpreter.getStringValue(characteristicValue, 0);
Log.d(TAG, "characteristicValue deviceHardware = " + deviceHardware);
},
throwable -> {
// Handle an error here.
}
)
Constants are defined like this:
public static final UUID CSC_MEASURE = UUID.fromString("00002a5b-0000-1000-8000-00805f9b34fb");
I tried to integrate the answer provided in here but the code doesn't compile anymore. Moreover, the code should combine up to 12 characteristics (simple map of UUID to Int/String/Boolean). I used to have a working code by creating a subclass of BluetoothGattCallback but my code was getting more and more difficult to maintain with standard Android Bluetooth classes.
I tried to integrate the answer provided in here but the code doesn't compile anymore.
I have updated the post you mentioned to match RxAndroidBle based on RxJava2. It should compile now.
I have another piece of working code to read ONE characteristic, but how can I process a list of characteristics?
...
Moreover, the code should combine up to 12 characteristics (simple map of UUID to Int/String/Boolean).
The mentioned post does solve a case where there are 4 characteristics. In case of 12 (or a variable number) there is a Single#zipArray function.
Single.zipArray(
/* Object[] */ results -> YourWrapperObject(results),
rxBleConnection.readCharacteristic(Constants.DEVICE_HARDWARE),
rxBleConnection.readCharacteristic(Constants.DEVICE_HARDWARE1),
rxBleConnection.readCharacteristic(Constants.DEVICE_HARDWARE2),
// ...
rxBleConnection.readCharacteristic(Constants.DEVICE_HARDWARE11)
)
I have setup pubnub on android using java
And on all other Operating Systems the setup works fine. On Android P however the attach listener always gives this error -
PNStatus(category=PNBadRequestCategory, errorData=PNErrorData(information=null, throwable=PubNubException(errormsg=CLEARTEXT communication to ps.pndsn.com not permitted by network security policy, pubnubError=PubNubError(errorCode=103, errorCodeExtended=0, errorObject=null, message=HTTP Error. Please check network connectivity. Please contact support with error details if issue persists., errorString=null), jso=null, response=null, statusCode=0)), error=true, statusCode=0, operation=PNSubscribeOperation, tlsEnabled=false, uuid=null, authKey=null, origin=null, clientRequest=null, affectedChannels=[5d67fb36f4f95718bf8ec310], affectedChannelGroups=[])
The setup is as follows -
PNConfiguration pnConfiguration = new PNConfiguration();
pnConfiguration.setLogVerbosity(PNLogVerbosity.BODY);
pnConfiguration.setPublishKey(getString(R.string.pubnub_publish_key));
pnConfiguration.setSubscribeKey(getString(R.string.pubnub_subscribe_key));
pnConfiguration.setSecure(false);
pubnub = new PubNub(pnConfiguration);
Then i attach listener like this
pubnub.addListener(new SubscribeCallback() {
#Override
public void status(PubNub pubnub, PNStatus status) {
Log.e("Pubnub:- ", status.toString());
switch (status.getOperation()) {
// let's combine unsubscribe and subscribe handling for ease of use
case PNSubscribeOperation:
case PNUnsubscribeOperation:
// note: subscribe statuses never have traditional
// errors, they just have categories to represent the
// different issues or successes that occur as part of subscribe
switch (status.getCategory()) {
case PNConnectedCategory:
// this is expected for a subscribe, this means there is no error or issue whatsoever
case PNReconnectedCategory:
// this usually occurs if subscribe temporarily fails but reconnects. This means
// there was an error but there is no longer any issue
case PNDisconnectedCategory:
// this is the expected category for an unsubscribe. This means there
// was no error in unsubscribing from everything
case PNUnexpectedDisconnectCategory:
// this is usually an issue with the internet connection, this is an error, handle appropriately
case PNAccessDeniedCategory:
// this means that PAM does allow this client to subscribe to this
// channel and channel group configuration. This is another explicit error
default:
// More errors can be directly specified by creating explicit cases for other
// error categories of `PNStatusCategory` such as `PNTimeoutCategory` or `PNMalformedFilterExpressionCategory` or `PNDecryptionErrorCategory`
}
case PNHeartbeatOperation:
// heartbeat operations can in fact have errors, so it is important to check first for an error.
// For more information on how to configure heartbeat notifications through the status
// PNObjectEventListener callback, consult <link to the PNCONFIGURATION heartbeart config>
if (status.isError()) {
// There was an error with the heartbeat operation, handle here
} else {
// heartbeat operation was successful
}
default: {
// Encountered unknown status type
}
}
}
#Override
public void message(PubNub pubnub, PNMessageResult message) {
String messagePublisher = message.getPublisher();
System.out.println("Message publisher: " + messagePublisher);
System.out.println("Message Payload: " + message.getMessage());
System.out.println("Message Subscription: " + message.getSubscription());
System.out.println("Message Channel: " + message.getChannel());
System.out.println("Message timetoken: " + message.getTimetoken());
}
#Override
public void presence(PubNub pubnub, PNPresenceEventResult presence) {
}
#Override
public void signal(PubNub pubnub, PNSignalResult pnSignalResult) {
System.out.println("Signal publisher: " + signal.getPublisher());
System.out.println("Signal payload: " + signal.getMessage());
System.out.println("Signal subscription: " + signal.getSubscription());
System.out.println("Signal channel: " + signal.getChannel());
System.out.println("Signal timetoken: " + signal.getTimetoken());
}
#Override
public void user(PubNub pubnub, PNUserResult pnUserResult) {
// for Objects, this will trigger when:
// . user updated
// . user deleted
PNUser pnUser = pnUserResult.getUser(); // the user for which the event applies to
pnUserResult.getEvent(); // the event name
}
#Override
public void space(PubNub pubnub, PNSpaceResult pnSpaceResult) {
// for Objects, this will trigger when:
// . space updated
// . space deleted
PNSpace pnSpace = pnSpaceResult.getSpace(); // the space for which the event applies to
pnSpaceResult.getEvent(); // the event name
}
#Override
public void membership(PubNub pubnub, PNMembershipResult pnMembershipResult) {
// for Objects, this will trigger when:
// . user added to a space
// . user removed from a space
// . membership updated on a space
JsonElement data = pnMembershipResult.getData(); // membership data for which the event applies to
pnMembershipResult.getEvent(); // the event name
}
#Override
public void messageAction(PubNub pubnub, PNMessageActionResult pnActionResult) {
PNMessageAction pnMessageAction = pnActionResult.getAction();
System.out.println("Message action type: " + pnMessageAction.getType());
System.out.println("Message action value: " + pnMessageAction.getValue());
System.out.println("Message action uuid: " + pnMessageAction.getUuid());
System.out.println("Message action actionTimetoken: " + pnMessageAction.getActionTimetoken());
System.out.println("Message action messageTimetoken: " + pnMessageAction.getMessageTimetoken());]
System.out.println("Message action subscription: " + pnActionResult.getSubscription());
System.out.println("Message action channel: " + pnActionResult.getChannel());
System.out.println("Message action timetoken: " + pnActionResult.getTimetoken());
}
});
Like i said it works fine in other OS's except 9 and i am using the latest version of pubnub, infact i upgraded to the latest version and the above error was identical.
And i noticed something else, a message which i see in the debugger that only shows up when running in android version 9.
isWhitelistProcess - Process is Whitelisted
I searched for the message and found that its a harmless warning message.
Enabling TLS (SSL) resolves this error:
pnConfiguration.setSecure(true);
The reason is answered in another Stack Overflow thread already. It is not specific to PubNub but because you disabled TLS (SSL) in PubNub, it explicitly called out the PubNub domain in the error.
Update:
After much research I've asked this question instead. It gets to the core of the problem. Google IMA webview is not showing when used inside react native on android
We are using react-native-video to use the exoplayer on android to show video with adds. The problem is, the exoplayer doesn't show the skip-button when an ad is skippable. To solve this problem we need to know if an ad is skippable and show a custom skipp-button. That's where I'm stuck. I can't get access to this information without changing the sourcecode of the exoplayer ima-extention.
The preferred solution would be to change the ImaAdsLoader**.onAdEvent() to broadcast an event when the add is loaded that exposes the Ad that has been loaded. Then monitor the playback-progress and show/hide a custom skipp-button.
Is there a way to get the information without altering the code of the ima-extention?
#Override
public void onAdEvent(AdEvent adEvent) {
AdEventType adEventType = adEvent.getType();
boolean isLogAdEvent = adEventType == AdEventType.LOG;
if (DEBUG || isLogAdEvent) {
Log.w(TAG, "onAdEvent: " + adEventType);
if (isLogAdEvent) {
for (Map.Entry<String, String> entry : adEvent.getAdData().entrySet()) {
Log.w(TAG, " " + entry.getKey() + ": " + entry.getValue());
}
}
}
if (adsManager == null) {
Log.w(TAG, "Dropping ad event after release: " + adEvent);
return;
}
Ad ad = adEvent.getAd();
switch (adEvent.getType()) {
case LOADED:
//This line is what I need
eventListener.onAdLoaded(ad);
// The ad position is not always accurate when using preloading. See [Internal: b/62613240].
AdPodInfo adPodInfo = ad.getAdPodInfo();
int podIndex = adPodInfo.getPodIndex();
adGroupIndex = podIndex == -1 ? adPlaybackState.adGroupCount - 1 : podIndex;
int adPosition = adPodInfo.getAdPosition();
int adCountInAdGroup = adPodInfo.getTotalAds();
adsManager.start();
if (DEBUG) {
Log.d(TAG, "Loaded ad " + adPosition + " of " + adCountInAdGroup + " in ad group "
+ adGroupIndex);
}
adPlaybackState.setAdCount(adGroupIndex, adCountInAdGroup);
updateAdPlaybackState();
break;
case CONTENT_PAUSE_REQUESTED:
// After CONTENT_PAUSE_REQUESTED, IMA will playAd/pauseAd/stopAd to show one or more ads
// before sending CONTENT_RESUME_REQUESTED.
imaPausedContent = true;
pauseContentInternal();
break;
case STARTED:
if (ad.isSkippable()) {
focusSkipButton();
}
break;
case TAPPED:
if (eventListener != null) {
eventListener.onAdTapped();
}
break;
case CLICKED:
if (eventListener != null) {
eventListener.onAdClicked();
}
break;
case CONTENT_RESUME_REQUESTED:
imaPausedContent = false;
resumeContentInternal();
break;
case ALL_ADS_COMPLETED:
// Do nothing. The ads manager will be released when the source is released.
default:
break;
}
}
I'm using
function Global_Events_OnStart(e) {
isNetworkUp = (Device.connectionType == 0);
}
to detect if network connected. At Home Screen's onShow event which hosts code to run Webclients:
function pgHome_Self_OnShow() {
if (isNetworkUp) {
wcPersonList.run(true); // async run
wcImages.run(true);
}else{
Dialogs.dlConnectionWarning.show();
}
}
Is this ok? Or should I add additional controls to Global Application.onError event?
With using isNetworkUp control you can use your own Error Dialog.
If you don't write any codeLines to detect that network is up or down,
It triggers Global_Events_OnError .
function Global_Events_OnError(e) {
switch (e.type) {
case "Server Error":
case "Size Overflow":
alert(lang.networkError);
break;
default:
SES.Analytics.eventLog("error", JSON.stringify(e));
//change the following code for desired generic error messsage
alert({
title : lang.applicationError,
message : e.message + "\n\n*" + e.sourceURL + "\n*" + e.line + "\n*" + e.stack
});
break;
}
}
Global_Events_OnError is predefined function to detect any kind of error in your project.
Smartface.io Team