Pusher: Trigger pusher events from android app - android

In an android app I was able to subscribe to a pusher channel and log out the event data. So now I want to be able to trigger events from the same application. I don't find documentation relating to this on the web.
Am I missing something because I also have a node express app in which I'm able to trigger and subscribe to events in the same app.
Below is my code for the Android app, I'm looking to trigger an event in the "responseAFunc" function which is wired to a button click.
I have also left out the all import statements and package statements.
public class MainActivity extends Activity {
private Button responseA;
private ActivityMainBinding binding;
private Pusher pusher;
private Channel channel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
responseA = binding.responseA;
PusherOptions options = new PusherOptions();
options.setCluster("eu");
pusher = new Pusher("*****************",options);
pusher.connect( new ConnectionEventListener() {
#Override
public void onConnectionStateChange(ConnectionStateChange change) {
Log.e("Pusher"," changed to " + change.getCurrentState());
}
#Override
public void onError(String message, String code, Exception e) {
Log.e("Pusher" ," connecting! msg:" + message + " " + code);
Log.e("Pusher", e.getMessage());
}
}, ConnectionState.ALL);
channel = pusher.subscribe("to-pusher");
channel.bind("message", new SubscriptionEventListener() {
#Override
public void onEvent(PusherEvent event) {
Log.i("Pusher", event.getData());
}
});
}
public void responseAFunc(View view){
// Trigger event
}
}
Hope this makes sense and HELLO from South Africa !!!

Hello from Amsterdam!
What you are looking for is "client events". Here are the docs: https://pusher.com/docs/channels/using_channels/events/#triggering-client-events
It's very easy: Once you got an instance for a channel you can just call the "trigger" method on it. Here are the docs for java: https://github.com/pusher/pusher-websocket-java#triggering-events
The harder part is that it will only work on private and presence channels. And then you will need to implement authentication. https://pusher.com/docs/channels/server_api/authenticating-users/

Related

WearableListenerService: calling putDataItem() multiple times

I have a list of 10 objects that I need to send from the handheld to the wearable. The sending works perfect for all of them, but onDataChanged() only gets triggered 2 times and it seems like the first one is random. So i recreated the exact same problem with the same results:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = findViewById(R.id.button);
mDataClient = Wearable.getDataClient(this);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for(int i = 0; i < 10; i++) {
//own mock up class with string id of i to differ them
Model model = new Model(String.valueOf(i)
, "title"
, new Date().getTime());
sendDataToWear(model);
}
}
});
}
private void sendDataToWear(Model model) {
PutDataMapRequest putDataMapRequest = PutDataMapRequest.create("/my_path");
putDataMapRequest.getDataMap().putString("id", model.getId());
putDataMapRequest.getDataMap().putString("title", model.getTitle());
putDataMapRequest.getDataMap().putLong("timestamp", model.getTimeStamp());
PutDataRequest putDataRequest = putDataMapRequest.asPutDataRequest();
Task<DataItem> putDataTask = mDataClient.putDataItem(putDataRequest);
putDataTask.addOnSuccessListener(new OnSuccessListener<DataItem>() {
#Override
public void onSuccess(DataItem dataItem) {
Log.d(TAG, "onSuccess: dataitem");
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, "onFailure: dataitem " + e.getMessage());
}
});
}
The onSuccess logs are called 10 times with the correct payload.
The wearable activity with implemented OnDataChangeListener:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Wearable.getDataClient(this).addListener(this);
}
#Override
public void onDataChanged(#NonNull DataEventBuffer dataEventBuffer) {
for(DataEvent event : dataEventBuffer) {
if(event.getType() == DataEvent.TYPE_CHANGED) {
DataItem item = event.getDataItem();
if(item.getUri().getPath().compareTo("/my_path") == 0) {
DataMap map = DataMapItem.fromDataItem(item).getDataMap();
Log.d(TAG, "onDataChanged: name: " + map.getString("id"));
}
}
}
}
onDataChanged logs are called 2 times with the first one always different and the second one always 9. I have no idea whats going on. I also tested it with 1 second wait time between the putDataItem() calls and it works as intended. The onDataChanged method is called 10 times and the 10 payloads are transfferred. But i cant wait one second between each call. Does somebody know whats going on here?
All your requests are being created with the same path, so later requests overwrite the earlier - and if this happens before the earlier requests have been sent to the phone (as is likely), it'll only receive the last one.
To send different items, use different paths in your PutDataMapRequest.create() calls. Preferably, create a path that sensibly differentiates each item (such as one that ends in a unique ID, like "/my_path/[item_id]").

WeChat InApp payment screen shows up only for first time

I'm trying to implement WeChat InApp payments in our app. But we are struggling to make it work.
I will try to sum it up real quick.
Given user is not logged in, WeChat login screen show up every time.
Given user is logged in, when clicked on pay button for a first time, WeChat order info screen shows up, but when clicked back, and clicked on pay button again (in our app), WeChat screen doesn’t show up.
We did implemented WXPayEntryActivity but neither onCreate, onNewIntent nor onResp are called. And yes, this activity is sending broadcast but neither toast nor log shows up.
I tried call registerApp on application started, I tried it just before creating payment req.
Did anybody come across this issue?
Can WeChat help me directly?
Want to see some code?
This is my payment class
public class WXInAppPayment {
public void startPayment(AppCompatActivity activity, PaymentDataResponse data) {
IWXAPI api = getApi(activity);
if (api.isWXAppInstalled()) {
api.sendReq(getPayRequest(data));
} else {
// Showing toast
}
}
public WXReceiver getReceiver() {
// returning BR for wechat payments
return new WXReceiver();
}
public IntentFilter getIntentFilter() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Constants.WE_CHAT_BR_ID);
return intentFilter;
}
private IWXAPI getApi(AppCompatActivity activity) {
final IWXAPI api = WXAPIFactory.createWXAPI(activity, null);
api.registerApp(Constants.WE_CHAT_APP_ID);
return api;
}
private PayReq getPayRequest(PaymentDataResponse data) {
PayReq request = new PayReq();
request.appId = dataFromAPI.appId;
request.partnerId = dataFromAPI.partnerId;
request.prepayId = dataFromAPI.prepayId;
request.packageValue = dataFromAPI.packageValue;
request.nonceStr = dataFromAPI.nonceStr;
request.timeStamp = dataFromAPI.timestimeStampamp;
request.sign = dataFromAPI.sign;
return request;
}
}
And this is WXPayEntryActivity. In manifest:
<activity android:name=".wxapi.WXPayEntryActivity"
android:label="#string/app_name"
android:exported="true"/>
And class:
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
private final String TAG = getClass().getSimpleName();
private IWXAPI api;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
api = WXAPIFactory.createWXAPI(this, Constants.WE_CHAT_APP_ID);
api.handleIntent(getIntent(), this);
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
}
#Override
public void onReq(BaseReq baseReq) {
Log.e(TAG, "onReq: " + baseReq.transaction);
}
#Override
public void onResp(BaseResp baseResp) {
Log.e(TAG, "onResp: " + baseResp.errStr + " " + baseResp.errCode);
Intent intent = new Intent(Constants.WE_CHAT_BR_ID);
intent.putExtra("error_code", baseResp.errCode);
intent.putExtra("error_string", baseResp.errStr);
sendBroadcast(intent);
finish();
}
}
I went through same issue... Your code look fine.
lets cover the scenario:
This is normal ... if user is not logged in.. Wechat App will
redirect to login screen
"Only first time payment passed" happened due to wrong packageName. consider these checks:
You need to use ApplicationId not packageName
WhiteSpace
Debug buildType by default has suffix: .debug to applicatonId
Check AppSign which is MD5 of cert you sign with.. Be careful not to use the default one for debug buildType.
Try to reassign ApplicationId and AppSign it again.(that was our issue 😞) due to hidden WS not visible.
Contact Wechat team support.. they have logs to payment.

Connect a client app Android to a server written with Sails.js using socket.io

Here's my situation: i have a server written with sails.js where i have a user model. I have a dashboard where i can see all the users, create new, delete them and so on...Now i want to create an android app where i can get, using socket.io, notification about the events that occour to the user model.
Example: if i delete a user from my dashboard i want the app to recive a notification from the server that the user has been deleted.
Here's my code for the app:
public class MainActivity extends Activity {
//socket instance
private Socket mSocket;
{
try {
mSocket = IO.socket("http://server_url:port/user");
} catch (URISyntaxException e) {
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); //set the layout for this activity
final TextView tv = (TextView) findViewById(R.id.textView);
mSocket.on("user", new Emitter.Listener() {
#Override
public void call(Object... args) {
tv.setVisibility(View.INVISIBLE);
}
});
mSocket.connect();
final Button btn_createUser = (Button)findViewById(R.id.button);
btn_createUser.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mSocket.connected()) {
//tv.setVisibility(View.INVISIBLE);
}
}
});
}
}
Like i did with the dashboard to connect the socket to the server i did the same thing here, but it seems like the socket doesn't connect, in fact, when i delete a user from the dashboard i get no notification.
Here's the code (that works) i used in my dashboard to connect my socket to the server and listen to updates from the user model:
//connect to the server and listen to updates from user model
io.socket.get('/user', function(data, jwres) {
$scope.users = data;
$scope.$apply(); //write users in the table...
});
//wait for updates...
io.socket.on('user', function serverResponded (data) {
if(data.verb == "updated")
{
//get the user index in the array and update it
var index = getIndex(data.id, $scope.users);
$scope.users[index].online = data.data.online;
$scope.$apply();
}
if(data.verb == "destroyed")
{
//get the user index in the array and remove it
var index = getIndex(data.id, $scope.users);
$scope.users.splice(index, 1);
$scope.$apply();
}
if(data.verb == "created")
{
//simply update the array
$scope.users.push(data.data);
$scope.$apply();
}
});
Now, i think all i'm missing out in the android app is the GET request which automatically subscribe my socket to the model and get notified if something happen...but i don't know hot to do it.
I hope i was clear enough...thank to everyone who will answer me!
PS: i don't want to use AndroidAsync because i need the ultimate version of socket.io!
In case someone need it, i found the solution: https://github.com/balderdashy/sails/issues/2640 here you can find out how to solve the issue! :)

How can I use Android TextToSpeak in a MVVMCross plugin?

I have seen plenty of examples of how to use Android TextToSpeak in an Activity, and have also managed to get this to work just fine. I've also managed to get it to work using a bound service in a plugin, but it seems overcomplicated for my purposes. Here is my VoiceService class:
public class VoiceService : IVoiceService, TextToSpeech.IOnInitListener
{
public event EventHandler FinishedSpeakingEventHandler;
private TextToSpeech _tts;
public void Init()
{
// Use a speech progress listener so we get notified when the service finishes speaking the prompt
var progressListener = new SpeechProgressListener();
progressListener.FinishedSpeakingEventHandler += OnUtteranceCompleted;
//_tts = new TextToSpeech(Application.Context, this);
_tts = new TextToSpeech(Mvx.Resolve<IMvxAndroidCurrentTopActivity>().Activity, this);
_tts.SetOnUtteranceProgressListener(progressListener);
}
public void OnInit(OperationResult status)
{
// THIS EVENT NEVER FIRES!
Console.WriteLine("VoiceService TextToSpeech Initialised. Status: " + status);
if (status == OperationResult.Success)
{
}
}
public void Speak(string prompt)
{
if (!string.IsNullOrEmpty(prompt))
{
var map = new Dictionary<string, string> { { TextToSpeech.Engine.KeyParamUtteranceId, new Guid().ToString() } };
_tts.Speak(prompt, QueueMode.Flush, map);
Console.WriteLine("tts_Speak: " + prompt);
}
else
{
Console.WriteLine("tts_Speak: PROMPT IS NULL OR EMPTY!");
}
}
/// <summary>
/// When we finish speaking, call the event handler
/// </summary>
public void OnUtteranceCompleted(object sender, EventArgs e)
{
if (FinishedSpeakingEventHandler != null)
{
FinishedSpeakingEventHandler(this, new EventArgs());
}
}
public void Dispose()
{
//throw new NotImplementedException();
}
public IntPtr Handle { get; private set; }
}
Note that the OnInit method never gets called.
In my viewmodel I'd like to do this:
_voiceService.Init();
_voiceService.FinishedSpeakingEventHandler += _voiceService_FinishedSpeakingEventHandler;
... and then later ...
_voiceService.Speak(prompt);
When I do this I get these messages in the output:
10-13 08:13:59.734 I/TextToSpeech( 2298): Sucessfully bound to com.google.android.tts
(happens when I create the new TTS object)
and
10-13 08:14:43.924 W/TextToSpeech( 2298): speak failed: not bound to TTS engine
(when I call tts.Speak(prompt))
If I was using an activity I would create an intent to get this to work, but I'm unsure how to do that in a plugin.
Thanks in advance,
David
Don't implement Handle yourself, instead derive from Java.Lang.Object
public class VoiceService : Java.Lang.Object, IVoiceService, TextToSpeech.IOnInitListener
and remove your Dispose() and Handle implementation
More info here: http://developer.xamarin.com/guides/android/advanced_topics/java_integration_overview/android_callable_wrappers/
Also, I suggest you take an async approach when implementing your service, which would make calling it from view-model something like
await MvxResolve<ITextToSpeechService>().SpeakAsync(text);

Codenameone when I read the qrCode uzing Zxing on Android the application goes back to 'init' and 'start'

I am using Codenameone and ZXing to read a QRCode. When I call the Scanner, my mobile opens the QRCode reader application and I get to read the QRCode except that when android takes me back to my app it goes through init then start statuses. Which moves me back to the login form of my application instead of continuing filling the form that I was in.
Any help on what to do to stay in the same form? Is there something I'm doing wrong? Thanks in advance.
EverproX.addMessage("Before Scan\n");
CodeScanner.getInstance().scanQRCode(new ScanResult() {
public void scanCompleted(String contents, String formatName, byte[] rawBytes) {
EverproX.addMessage("Scan Completed "+contents);
}
public void scanCanceled() {
EverproX.addMessage("Scan Cancelled");
}
public void scanError(int errorCode, String message) {
EverproX.addMessage("Scan Error "+errorCode+" "+message);
}
});
EverproX can be seen as a log class.
By analyzing our log we can say that as soon as we call the CodeScanner.getInstance().scanQRCode() the application is called for 'Destroy'. Then after the scanning is done it goes again through the init and start. It never goes into the scanComplete scanCanceled or scanError Callbacks.
Is it normal that the App is destroyed upon call of CodeScanner? Many thanks.
Inside your codenameone project, you should find a class named (for example MyApp.java) based on your app's name, modify the code to read something like similar to this:
public class MyApp {
private Form current;
public void init(Object context) {
// Pro users - uncomment this code to get crash reports sent to you automatically
Display.getInstance().addEdtErrorHandler(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
evt.consume();
Log.p("Exception in AppName version " + Display.getInstance().getProperty("AppVersion", "Unknown"));
Log.p("OS " + Display.getInstance().getPlatformName());
Log.p("Error " + evt.getSource());
Log.p("Current Form " + Display.getInstance().getCurrent().getName());
Log.e((Throwable) evt.getSource());
Log.sendLog();
}
});
}
public void start() {
if (current != null) {
current.show();
return;
}
new StateMachine("/theme");
}
public void stop() {
current = Display.getInstance().getCurrent();
}
public void destroy() {
current = null;
}
}

Categories

Resources