QuickBlox chat messages listener - java

I use 2.1.1 Android SDK and want to notify user about new incoming messages received by application.
Here is the issue. I would like to notify user as he launches application, thus i would like to add listener at the stage of "user login" as it's shown in the snippet:
QBAuth.createSession(user, new QBEntityCallbackImpl<QBSession>() {
#Override
public void onSuccess(QBSession session, Bundle args) {
// login to Chat
chatService.login(user, new QBEntityCallbackImpl() {
#Override
public void onSuccess() {
HERE I WOULD LIKE A CODE TO START LISTEN FOR ALL INCOMING MESSAGES
As per http://sdk.quickblox.com/android/com/quickblox/chat/listeners/QBMessageListenerImpl.html
listener needs chat QBChat to initiate. But I would like to listen for all of the messages, not only within particular chat.
Long story short, how to implement a message listener to catch all messages addressed to logged in user?

#Naveen Kumar
In my start activity i launch listener to catch XMPP connection.
private void XMPPConnectionListener() {
XMPPConnection.addConnectionCreationListener(new ConnectionCreationListener() {
#Override
public void connectionCreated(XMPPConnection connection) {
GlobalVar.XMPPConn = connection;
ChatHelper.idleMessageListener(StartActivity.this);
}
});
}
Then I use GlobalVar.XMPPConn to catch packets and parse them:
public static void idleMessageListener(final Activity activity) {
PacketListener myListener = new PacketListener() {
public void processPacket(final Packet packet) {
final Integer userID = Integer.parseInt(returnIDFromPacket(packet.getFrom()));
final String body = returnBodyFromPacket(packet.toString());
if (!GlobalVar.currentOpponent.equals(userID) && !body.isEmpty()) {
activity.runOnUiThread(new Runnable() {
public void run() {
QBUsers.getUser(userID, new QBEntityCallbackImpl<QBUser>() {
#Override
public void onSuccess(final QBUser user, Bundle args) {
sendNotification(activity, user, body);
}
#Override
public void onError(List<String> errors) {
Log.d(TAG, errors.toString());
}
});
}
});
}
}
};
PacketFilter filter = new MessageTypeFilter(Message.Type.chat);
if (GlobalVar.XMPPConn != null) {
GlobalVar.XMPPConn.addPacketListener(myListener, filter);
}
}
So logic is to catch the connection fired by QuickBlox and then attach a packet listener to it.

Related

How to close WebSockets properly from Application class?

I am using WebSockets for my chat app in android. For convenience, I am creating the connection in Application class so that it can be used by activities and fragments with one instance. Here is the code for my Application class:
public class Main extends Application implements LifecycleObserver {
private static WeakReference<Context> context;
private WebSocket webSocket;
private final Request request;
private final OkHttpClient client;
public static final int SOCKET_CLOSE_CODE = 1000;
#Override
public void onCreate() {
super.onCreate();
context = new WeakReference<>(getApplicationContext());
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
this.client = new OkHttpClient();
this.request = new Request.Builder().url("ws://192.168.1.9:8080").build();
}
public void connect() {
webSocket = client.newWebSocket(request, new WebSocketListener() {
#Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
}
#Override
public void onMessage(WebSocket webSocket, String text) {
super.onMessage(webSocket, text);
}
#Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
super.onMessage(webSocket, bytes);
}
#Override
public void onClosing(WebSocket webSocket, int code, String reason) {
super.onClosing(webSocket, code, reason);
}
#Override
public void onClosed(WebSocket webSocket, int code, String reason) {
super.onClosed(webSocket, code, reason);
}
#Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
super.onFailure(webSocket, t, response);
}
});
}
#OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume() {
if (webSocket == null) return;
connect();
}
#OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause() {
if (webSocket == null) return;
disconnect();
}
private void disconnect() {
webSocket.close(SOCKET_CLOSE_CODE, null);
webSocket = null;
}
#OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onDestroy() {
if (client == null) return;
client.connectionPool().evictAll();
client.dispatcher().executorService().shutdown();
}
}
For some reason, the socket does not close in either onPause or onDestroy (tried both). I am using Ratchet in server side. What's wrong with this code? Note that I want to close the connection exactly from the Application class itself instead of closing from activities or fragments or any other components.
The answer might be WebSocketActivity extends FragmentActivity implements WebSocketListener {} because Activity would implement these lifecycle methods, therefore they can be overridden.

How to run RecognitionListener at the background of the app?

everyone! I am developing an application for voice recognition, and the application is able to recognize the speech right now! However, I need to run this voice recognition code at the background of the app, it has to listen to the commands all the time. For my app, I wrote Handler().postDelayed function, it calculates the time when the user lands a new activity and it starts listening by delaying for 5 seconds. My problem is that it just listens 2-3 seconds, and it is not able to recognize and listen again. How can I run voice recognition at the background of the app when the app is running?
speechRecognizer1.setRecognitionListener(new RecognitionListener() {
#Override
public void onReadyForSpeech(Bundle params) {
}
#Override
public void onBeginningOfSpeech() {
}
#Override
public void onRmsChanged(float rmsdB) {
}
#Override
public void onBufferReceived(byte[] buffer) {
}
#Override
public void onEndOfSpeech() {
}
#Override
public void onError(int error) {
}
#Override
public void onResults(Bundle bundle) {
ArrayList<String> matches1 =bundle.getStringArrayList(speechRecognizer1.RESULTS_RECOGNITION);
String string="";
if(matches1!=null) {
string = matches1.get(0);
textView3.setText(string);
Speak();
}
}
#Override
public void onPartialResults(Bundle bundle) {
}
#Override
public void onEvent(int eventType, Bundle params) {
}
});
mTTS1 = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(status==TextToSpeech.SUCCESS){
int result= mTTS1.setLanguage(Locale.ENGLISH);
if(result== TextToSpeech.LANG_MISSING_DATA || result==TextToSpeech.LANG_NOT_SUPPORTED){
Log.e("TTS","Language Not Supported");
}
}
}
});
new Handler().postDelayed(new Runnable(){
public void run(){
speechRecognizer1.startListening(intentRecognizer1);
}
}, 5000);
Ok for this you need an android component called Service
we have three types of services in android :
1.Forground:
a foreground service do works that is noticeable to the user for example a music app with a notification about the song that is playing.
2.Background:
this service is not noticeable to the user
3.Bound:
and bound service which offers the user a client-server interaction
for your case you can use a foreground service.
to decide what is better and how to implement it or deciding between a thread and a service I recommend reading this document :
https://developer.android.com/guide/components/services

How to get play and stop event callback from chromecast android

I want to get callback event and perform some function when chromecast audio change there playback mode(play/stop)
How can I get the play/stop event to the application so I will do my work on that event.
Please check below logic I have implemented.
private void setupCastListener() {
mSessionManagerListener = new SessionManagerListener<CastSession>() {
#Override
public void onSessionEnded(CastSession session, int error) {
onApplicationDisconnected();
}
#Override
public void onSessionResumed(CastSession session, boolean wasSuspended) {
onApplicationConnected(session);
}
#Override
public void onSessionResumeFailed(CastSession session, int error) {
onApplicationDisconnected();
}
#Override
public void onSessionStarted(CastSession session, String sessionId) {
onApplicationConnected(session);
}
#Override
public void onSessionStartFailed(CastSession session, int error) {
onApplicationDisconnected();
}
#Override
public void onSessionStarting(CastSession session) {
}
#Override
public void onSessionEnding(CastSession session) {
}
#Override
public void onSessionResuming(CastSession session, String sessionId) {
if(mCastSession!=null && isChromeCastConnected){
try {
if (session.isMute()) {
mStopPlayButton.setImageResource(R.drawable.ic_play);
isChromeCastPlay = false;
//mCastSession.setMute(!mCastSession.isMute());
} else {
mStopPlayButton.setImageResource(R.drawable.ic_stop);
isChromeCastPlay = true;
//mCastSession.setMute(!mCastSession.isMute());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
public void onSessionSuspended(CastSession session, int reason) {
}
};
}
Please let me know. thanks
You need to read this documentation, and focus on RemoteMediaClient and the Listener interface there. The callback onStatusUpdated() will be called when there is a change in the playback status. Tutorials available on the first link above is very informative, so make sure you read about things there.
Finally I found the remote media play and pause mode call back by below MediaControlIntent.
Remote Playback Routes
mMediaRouter = MediaRouter.getInstance(this);
mSelector = new MediaRouteSelector.Builder()
.addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
.build();

Communication between Activity and GCMListenerService Android

I am working on an android application with push notification feature using GCM. I have created a class called PushNotificationService which extends GCMListenerService. Inside the onMessageReceived(String from, Bundle data) I am able to get the message in the push notification.
Now, I want to access a method inside my MainActivity class whenever a particular message is received in the push.
Below is my code :-
PushNotificationService.java
public class PushNotificationService extends GcmListenerService {
#Override
public void onMessageReceived(String from, Bundle data) {
// TODO Auto-generated method stub
super.onMessageReceived(from, data);
String message = data.getString("message");
if(message.equalsIgnoreCase("Begin Task"))
{
//call method from MainActivity.class
}
}
}
MainActivty.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void beginTask()
{
Log.d("GCM","Message Received from Server");
finish();
}
}
I want the beginTask() method to execute whenever the message "Begin Task" is received.
I know one approach is via Service->Interface->Activity architecture but I am not able to use this as I never create an object of PushNotificationService.
Please help.
UPDATE :-
I am now using Otto Library and below is my code.
Added new MyBus.java
public class MyBus extends Bus {
private static Bus bus;
//isRegistered is used to track the current registration status
private static boolean isRegistered;
private Handler handler = new Handler(Looper.getMainLooper());
public MyBus() {
if (bus == null) {
//ANY will allow event bus to run even with services
//and broadcast receivers
bus = new Bus(ThreadEnforcer.ANY);
}
}
#Override
public void register(Object obj) {
//The bus is registered when an activity starts
bus.register(obj);
isRegistered = true;
}
#Override
public void unregister(Object obj) {
//The bus is unregistered when an activity goes to background
bus.unregister(obj);
isRegistered = false;
}
#Override
public void post(final Object event) {
if (Looper.myLooper() == Looper.getMainLooper()) {
//post the event in main thread or background thread
bus.post(event);
} else {
handler.post(new Runnable() {
#Override
public void run() {
bus.post(event);
}
});
}
}
public boolean isRegistered(){
return isRegistered;
}
}
PushNotificationService.java
public class PushNotificationService extends GcmListenerService {
#Override
public void onMessageReceived(String from, Bundle data) {
// TODO Auto-generated method stub
super.onMessageReceived(from, data);
MyBus myBus = new MyBus();
myBus.register(myBus);
String message = data.getString("message");
if(message.equalsIgnoreCase("Begin Task"))
{
myBus.post(message);
}
}
}
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Subscribe
public void beginTask()
{
Log.d("GCM","Message Received from Server");
}
}
The problem is still not solved. The beginTask() inside MainActivity.java is still not getting called.
Use eventBus libraries to facilitate this process...
I use Otto for this process
http://square.github.io/otto/
Here is an another eventBus library https://greenrobot.github.io/EventBus/
Steps:
1.Create an event from the service
2.Add a listener in the activity
3.If the activity is running the method will be executed
**EDIT 1 : **
I have abstracted the otto bus like this.
package com.mypackage.eventBus;
import android.os.Handler;
import android.os.Looper;
import com.squareup.otto.Bus;
import com.squareup.otto.ThreadEnforcer;
/**
* Created by gowtham on 10/6/15.
*/
public class MyBus extends Bus {
private static Bus bus;
//isRegistered is used to track the current registration status
private static boolean isRegistered;
private Handler handler = new Handler(Looper.getMainLooper());
public MyBus() {
if (bus == null) {
//ANY will allow event bus to run even with services
//and broadcast receivers
bus = new Bus(ThreadEnforcer.ANY);
}
}
#Override
public void register(Object obj) {
//The bus is registered when an activity starts
bus.register(obj);
isRegistered = true;
}
#Override
public void unregister(Object obj) {
//The bus is unregistered when an activity goes to background
bus.unregister(obj);
isRegistered = false;
}
#Override
public void post(final Object event) {
if (Looper.myLooper() == Looper.getMainLooper()) {
//post the event in main thread or background thread
bus.post(event);
} else {
handler.post(new Runnable() {
#Override
public void run() {
bus.post(event);
}
});
}
}
public boolean isRegistered(){
return isRegistered;
}
}
create an instance of the above object and try posting event
EDIT 2 for Jcarlo's comment
Follow these steps to find the state of the activity.
In your activity's onResume call MyBus.getInstance().register(this).
In your activity's onPause call MyBus.getInstance().unregister(this).
In your GCM IntentService before posting the message
if(MyBus.getInstance().isRegistered()){
//app is alive
//post data
}else{
//show notification
}
Hope this helps
You can use LocalBroadcastManager. Create a LocalBroadcastManager object mBroadcaster = LocalBroadcastManager.getInstance(this); on onCreate of your GCMListener and send broadcast with
#Override
public void onCreate() {
super.onCreate();
mBroadcaster = LocalBroadcastManager.getInstance(this);
}
#Override
public void onMessageReceived(String from, Bundle data) {
super.onMessageReceived(from, data);
String message = data.getString("message");
if(message.equalsIgnoreCase("Begin Task")) {
Intent i = new Intent();
i.setAction("yourPackageName");
i.putExtra("DATA", yourData);
mBroadcaster.send(i);
}
}
Then you can receive message in MainActivity using a BroadcastReceiver.
BroadCastReceiver mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
beginTask();
}
};
Also you need to register and unregister the receiver in onStart and onStop of your activity
#Override
protected void onStart() {
super.onStart();
IntentFilter filter = new IntentFilter();
filter.addAction("yourPackageName);
LocalBroadcastManager.getInstance(this).registerReceiver((mBroadcastReceiver), filter);
}
#Override
protected void onStop() {
super.onStop();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
}

Accept Call between Android and iOS in QuickBlox

I use the framework to create a video messenger between Android and IOS.
To do: in iOS session is created and the user is called, which enters with the Android device.
But during the call, before making a call on android - android application crashes.
Maybe someone faced the such? Or what am I doing wrong? I do not understand how to handle the incoming call ... (
My code for Android device
onCreate(...){
QBSettings.getInstance().fastConfigInit(APPLICATION_ID,AUTHORIZATION_KEY,AUTHORIZATION_SECRET);
}
public void createSessionButton(View view){
//Log.d("Tag","onSuccess");
QBAuth.createSession(currentUser,new QBEntityCallbackImpl<QBSession>() {
#Override
public void onSuccess(QBSession session, Bundle params) {
currentUser.setId(session.getUserId());
Log.d("Tag","call set id success");
QBChatService chatService;
if (!QBChatService.isInitialized()) {
Log.d("Tag","QBChatService do not initialize");
QBChatService.init(getApplicationContext());
}
chatService = QBChatService.getInstance();
Log.d("Tag","QBChatService initialize");
// LOG IN CHAT SERVICE
chatService.login(currentUser, new QBEntityCallbackImpl<QBUser>() {
#Override
public void onSuccess() {
runOnUiThread(new Runnable() {
#Override
public void run() {
processTextView.setText("LOG IN CHAT SERVICE onSuccess");
}
});
//processTextView.setText("LOG IN CHAT SERVICE onSuccess");
Log.d("Tag","LOG IN CHAT SERVICE onSuccess");
}
#Override
public void onError(List errors) {
Log.d("Tag","LOG IN CHAT SERVICE onError");
}
});
}
#Override
public void onError(List<String> errors) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Важное сообщение!")
.setMessage("onError")
//.setIcon(R.drawable.ic_android_cat)
.setCancelable(false)
.setNegativeButton("ОК",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
});
}
public void createSignalingManager(View view) {
QBChatService.getInstance().getVideoChatWebRTCSignalingManager().addSignalingManagerListener(new QBVideoChatSignalingManagerListener() {
#Override
public void signalingCreated(QBSignaling qbSignaling, boolean b) {
if (!b) {
QBRTCClient.getInstance().addSignaling((QBWebRTCSignaling) qbSignaling);
runOnUiThread(new Runnable() {
#Override
public void run() {
processTextView.setText("addSignalingManagerListener");
}
});
}
}
});
// Add activity as callback to RTCClient
QBRTCClient.getInstance().addSessionCallbacksListener(this);
QBRTCClient.getInstance().addConnectionCallbacksListener(this);
QBRTCClient.getInstance().addVideoTrackCallbacksListener(this);
QBRTCClient.getInstance().prepareToProcessCalls(this);
}
My code in iOS
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[QBRTCClient.instance addDelegate:self];
[[QBChat instance] addDelegate:self];
[QBRTCConfig setDisconnectTimeInterval:10];
self.callTestButton.hidden = YES;
}
#pragma mark - Action
- (IBAction)loginAction:(id)sender {
QBUUser* currentUser = [[QBUUser alloc] init];
currentUser.password = pass;
currentUser.login = login;
// connect to Chat
[[QBChat instance] connectWithUser:currentUser completion:^(NSError * error) {
NSLog(#"Error: %#", error);
}];
[QBRequest logInWithUserLogin:login password:pass successBlock:^(QBResponse *response, QBUUser *user) {
NSLog(#"logInWithUserLogin:");
[QBRequest usersWithSuccessBlock:^(QBResponse * response, QBGeneralResponsePage * page, NSArray * users) {
NSLog(#"usersWithSuccessBlock:");
self.callTestButton.hidden = NO;
} errorBlock:^(QBResponse * response) {
}];
} errorBlock:^(QBResponse *response) {
NSLog(#"error: %#", response.error);
}];
}
- (IBAction)callAction:(UIButton *)sender {
NSArray *opponentsIDs = [[NSArray alloc] initWithObjects:[NSNumber numberWithInteger:6919398], nil];
NSLog(#"%ld", (long)[opponentsIDs[0] integerValue]);
QBRTCSession* session = [QBRTCClient.instance createNewSessionWithOpponents:opponentsIDs
withConferenceType:QBRTCConferenceTypeAudio];
session.localMediaStream.videoTrack.enabled = NO;
if (session) {
NSLog(#"new session");
}
NSDictionary *userInfo = #{#"startCall" : #"userInfo"};
[session startCall:userInfo];
}
Please check the documentation that shows how to use Quickblox SDK for videocalls and also check the sample code

Categories