i was try to create login session with session key, the session key always generate new key either we do Login/registration, i can retrieve the data from my gson
LoginService loginService = retrofit.create(LoginService.class);
Observable<LoginResponse> obs = loginService.logins(emai,pass,"1", Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID), Build.MODEL, Build.VERSION.RELEASE);
obs.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).
subscribe(new Observer<LoginResponse>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
public void onNext(LoginResponse loginResponse) {
int responses = loginResponse.getCODE();
String texts="";
if(responses == 1)
{
User user = loginResponse.getDATALIST().get(0);
setPrefIsLogin(true);
setPrefSessionUid(user.getSESSIONKEY(),user.getUSERID());
nextActivity();
}
else{
}
}
});
the question is, how to make handler to handle the save session check if there is another login activity with the same account?
You should never assign two accessToken/Session for one user. You will send the same accessToken to the other instance of the new user. Plus side, user won't be able to duplicate his/her work by two accessToken.
If you want to force the other/first one AUTO-LOGOUT, you can use Firebase notification feature to send a notification to that particular deviceID and force it to stop. You can check firebase's tutorial to see how they work.
Another slow procedure is to check before login & everyother server side work to check if there are instance of same user. You will send an error and user end will receive it and show the error accompanying by logging out the user.
Related
I am implementing AWS with an Android application for the first time.
We would like to use Cognito to authenticate our users, and selectively provide data from DynamoDB.
I have successfully set up my user pool and can see new registrations appear in the user list. Trying to login with an email that does not exist fails.
However, Cognito always logs in with a valid email address, regardless of password input.
What is wrong with my process?
public class CognitoController extends Application {
static CognitoUserPool pool;
static String userEmail;
public void onCreate(){
super.onCreate();
pool = new CognitoUserPool(this,
"us-east-xxxx",
"xxxx",
"xxxx",
new ClientConfiguration(),
Regions.US_EAST_1);
}
}
-
private void actionAdminLogin(){
UtilityInterfaceTools.hideSoftKeyboard(AdminLoginActivity.this);
String inputEmail = ((EditText) findViewById(R.id.input_admin_email)).getText().toString();
String inputPassword = ((EditText) findViewById(R.id.input_admin_password)).getText().toString();
CognitoController.userEmail = inputEmail;
details = new AuthenticationDetails(inputEmail, inputPassword, null);
AuthenticationHandler auther = new AuthenticationHandler() {
#Override
public void onSuccess(CognitoUserSession userSession, CognitoDevice newDevice) {
Toast.makeText(AdminLoginActivity.this, "Congratulations It Works...", Toast.LENGTH_LONG).show();
startActivity(new Intent(AdminLoginActivity.this, AdminPortalActivity.class));
finish();
}
#Override
public void getAuthenticationDetails(AuthenticationContinuation continuation, String email) {
continuation.setAuthenticationDetails(details);
continuation.continueTask();
}
#Override
public void getMFACode(MultiFactorAuthenticationContinuation continuation) {
continuation.continueTask();
}
#Override
public void authenticationChallenge(ChallengeContinuation continuation) {
continuation.continueTask();
}
#Override
public void onFailure(Exception exception) {
TextView errorMessage = findViewById(R.id.message_invalid_credentials);
errorMessage.setText(exception.toString());
errorMessage.setVisibility(View.VISIBLE);
}
};
CognitoController.pool.getUser(inputEmail).getSessionInBackground(auther);
}
I think your problem (which is not a problem by the way) is either:
In your pool Cognito setting, you chose your devices to be remembered.
Remembered
devices are also tracked. During user authentication, the key and secret pair assigned to a remembered device is used to authenticate the device to verify that it is the same device that the user previously used to sign in to the application. APIs to see remembered devices have been added to new releases of the Android, iOS, and JavaScript SDKs. You can also see remembered devices from the Amazon Cognito console.
The token is already cached:
Caching
The Mobile SDK for Android caches the last successfully authenticated user and the user's tokens locally on the device, in SharedPreferences. The SDK also provides methods to get the last successfully authenticated user.
Your Application Update
In fact for better user experience, you want the user to use the app, and don't need to login every time that she wants to use your app (e.g., look at mail apps, social media apps, etc.). However, you application need to handle that, you have two choices here:
Redirect to login if necessary: If the user is already logged in and wants to use the application again, your app needs to verify the user against the Cognito user pool, and only then, redirect the user to the login page if necessary.
Remove the token: If you really want the user to login every time that she uses the application, then remove the token if the user signs out; but I do not recommend this, for the sake of user experience.
I have an Android Application which talks to a server through REST APIs web services. I need to apply session management in android application. At the server side if there is 15 mins of inactivity the user will get logged out and a new authentication token is generated.I want to do session management in my android application. I am using Volley for the network calls.
REASON behind doing this:
I want to apply session management because after 15 mins of inactivity the server will generate a new token key and invalidate the session. Then the android application needs to have the new token key generated by the server for authentication and successful web service call.
What I have till now for session management in Android:
My MainActivity code:
public class MainActivity extends AppCompatActivity {
public static final long DISCONNECT_TIMEOUT = 600000;// 15 min
private Handler disconnectHandler = new Handler() {
public void handleMessage(Message msg) {
}
};
private Runnable disconnectCallback = new Runnable() {
#Override
public void run() {
// Perform any required operation for log out
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
}
};
public void resetDisconnectTimer() {
disconnectHandler.removeCallbacks(disconnectCallback);
disconnectHandler.postDelayed(disconnectCallback, DISCONNECT_TIMEOUT);
}
public void stopDisconnectTimer() {
disconnectHandler.removeCallbacks(disconnectCallback);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void onUserInteraction() {
resetDisconnectTimer();
}
#Override
public void onResume() {
super.onResume();
resetDisconnectTimer();
}
#Override
public void onStop() {
super.onStop();
stopDisconnectTimer();
}
}
How can I check if the session has be timed out at the server side or How can I logout the user after 15mins of inactivity.
Like you said, In your server side, you should have a token and a expiration date which you should always check, on every user request. Token becomes invalid If the date expired and no more response will user get until start new session (this way, you can redirect to login page, because server response is 'invalid token' or ' session time ellapsed').
In other words, in a simply way, no one needs to be watching if session is already expired. Only when user makes a new request, there the server validates user session. It's secure enough.
As previous Answers stated you should let the server ( the REST API ) handle that.
On every request from your android application send the token you have as a header ( just best practice ) and let the server validate that token first at all times before doing anything else. If the token is not valid anymore you can let him send you a special response with HTTP 401 or some other HTTP Code, telling you that your session timed out.
In your Android application you have to handle this response and automatically start/redirect to the login. Once he is logged in everything is as usual.
If you want you can try to remember where the user was before getting thrown out and redirect back to that activity after he is authorized again.
Here are some resources for REST session management:
https://www.quora.com/What-is-the-best-way-of-session-management-in-REST-architecture
If REST applications are supposed to be stateless, how do you manage sessions?
http://blog.synopse.info/post/2011/05/24/How-to-implement-RESTful-authentication
https://www.owasp.org/index.php/REST_Security_Cheat_Sheet
You don't have to use any session management in android application, better for every request you have to send the token within header params, in server-side the token authentication is taken care and returns the response JSON, in client-side you have to apply logic with respect to response JSON
How do I handle situation, when user logs out of my application and I no longer want him to receive notifications to the device.
I tried
FirebaseInstanceId.getInstance().deleteToken(FirebaseInstanceId.getInstance().getId(), FirebaseMessaging.INSTANCE_ID_SCOPE)
But I still receive the notifications to my device's registration_id.
I also made sure that this is the token I should delete:
FirebaseInstanceId.getInstance().getToken(FirebaseInstanceId.getInstance().getId(), FirebaseMessaging.INSTANCE_ID_SCOPE)
or simply FirebaseInstanceId.getInstance().getToken()).
I also tried FirebaseInstanceId.getInstance().deleteInstanceId(), but then the next time I call FirebaseInstanceId.getInstance.getToken I receive null (it works on the second try).
I guess, after deleteInstanceId I could immediately call getToken() again, but it looks like a hack. And also there's this answer which states that it shouldn't be done, but it proposes deleting the token which apparently doesn't work.
So what is the right method to handle this?
Okay. So I managed to do some testing and have concluded the following:
deleteToken() is the counterpart of getToken(String, String), but not for getToken().
It only works if the Sender ID you are passing is a different Sender ID (not the same ID that can be seen in your google-services.json). For example, you want to allow a different Server to send to your app, you call getToken("THEIR_SENDER_ID", "FCM") to give them authorization to send to your app. This will return a different registration token that corresponds only to that specific sender.
In the future, if you chose to remove their authorization to send to your app, you'll then have to make use of deleteToken("THEIR_SENDER_ID", "FCM"). This will invalidate the corresponding token, and when the Sender attempts to send a message, as the intended behavior, they will receive a NotRegistered error.
In order to delete the token for your own Sender, the correct handling is to use deleteInstanceId().
Special mentioning this answer by #Prince, specifically the code sample for helping me with this.
As #MichałK already doing in his post, after calling the deleteInstanceId(), getToken() should be called in order to send a request for a new token. However, you don't have to call it the second time. So long as onTokenRefresh() onNewToken() is implemented, it should automatically trigger providing you the new token.
For short, deleteInstanceId() > getToken() > check onTokenRefresh() onNewToken().
Note: Calling deleteInstanceId() will not only delete the token for your own app. It will delete all topic subscriptions and all other tokens associated with the app instance.
Are you positive you're calling deleteToken() properly? The value for audience should be (also seen from my answer that you linked) is "set to the app server's sender ID". You're passing the getId() value which is not the same as the Sender ID (it contains the app instance id value). Also, how are you sending the message (App Server or Notifications Console)?
getToken() and getToken(String, String) returns different tokens. See my answer here.
I also tried FirebaseInstanceId.getInstance().deleteInstanceId(), but then the next time I call FirebaseInstanceId.getInstance.getToken I receive null (it works on the second try).
It's probably because the first time you're calling the getToken(), it's still being generated. It's just the intended behavior.
I guess, after deleteInstanceId I could immediately call getToken() again, but it looks like a hack.
Not really. It's how you'll get the new generated (provided that it is already generated) token. So I think it's fine.
I did a brief research on what would be the most elegant solution to get back the full control (subscribe and unsubscribe to FCM) as before. Enable and disable the FCM after the user logged in or out.
Step 1. - Prevent auto initialization
Firebase now handle the InstanceID and everything else which need to generate a registration token. First of all you need to prevent auto initialization. Based on the official set-up documentation you need to add these meta-data values to your AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<application>
<!-- FCM: Disable auto-init -->
<meta-data android:name="firebase_messaging_auto_init_enabled"
android:value="false" />
<meta-data android:name="firebase_analytics_collection_enabled"
android:value="false" />
<!-- FCM: Receive token and messages -->
<service android:name=".FCMService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
</application>
Now you disabled the automatic token request process. At the same time you have an option to enable it again at runtime by code.
Step 2. - Implement enableFCM() and disableFCM() functions
If you enable the auto initialization again then you received a new token immediately, so this is a perfect way to implement the enableFCM() method.
All subscribe information assigned to InstanceID, so when you delete it then initiate to unsubscribe all topic. On this way you able to implement disableFCM() method, just turn back off auto-init before you delete it.
public class FCMHandler {
public void enableFCM(){
// Enable FCM via enable Auto-init service which generate new token and receive in FCMService
FirebaseMessaging.getInstance().setAutoInitEnabled(true);
}
public void disableFCM(){
// Disable auto init
FirebaseMessaging.getInstance().setAutoInitEnabled(false);
new Thread(() -> {
try {
// Remove InstanceID initiate to unsubscribe all topic
// TODO: May be a better way to use FirebaseMessaging.getInstance().unsubscribeFromTopic()
FirebaseInstanceId.getInstance().deleteInstanceId();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
Step 3. - FCMService implementation - token and message receiving
In the last step you need to receive the new token and send direct to your server.
Other hand you'll receive your data message and just do it what you want.
public class FCMService extends FirebaseMessagingService {
#Override
public void onNewToken(String token) {
super.onNewToken(token);
// TODO: send your new token to the server
}
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
String from = remoteMessage.getFrom();
Map data = remoteMessage.getData();
if (data != null) {
// TODO: handle your message and data
sendMessageNotification(message, messageId);
}
}
private void sendMessageNotification(String msg, long messageId) {
// TODO: show notification using NotificationCompat
}
}
I think this solution is clear, simple and transparent. I tested in a production environment and it's works. I hope it was helpful.
I was working on the same problem, when I had done my logout() from my application. But the problem was that after logging out, I was still getting push notifications from Firebase. I tried to delete the Firebase token. But after deleting the token in my logout() method, it is null when I query for it in my login() method. After working 2 days I finally got a solution.
In your logout() method, delete the Firebase token in the background because you can not delete Firebase token from the main thread
new AsyncTask<Void,Void,Void>() {
#Override
protected Void doInBackground(Void... params) {
try
{
FirebaseInstanceId.getInstance().deleteInstanceId();
} catch (IOException e)
{
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// Call your Activity where you want to land after log out
}
}.execute();
In your login() method, generate the Firebase token again.
new AsyncTask<Void,Void,Void>() {
#Override
protected Void doInBackground(Void... params) {
String token = FirebaseInstanceId.getInstance().getToken();
// Used to get firebase token until its null so it will save you from null pointer exeption
while(token == null) {
token = FirebaseInstanceId.getInstance().getToken();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
}
}.execute();
Developers should never unregister the client app as a mechanism for
logout or for switching between users, for the following reasons:
A registration token isn't associated with a particular logged in user. If the client app unregisters and then re-registers, the app can
receive the same registration token or a different registration token.
Unregistration and re-registration may each take up to five minutes to propagate. During this time messages may be rejected due to the
unregistered state, and messages may go to the wrong user. To make
sure that messages go to the intended user:
The app server can maintain a mapping between the current user and the registration token.
The client app can then check to ensure that messages it receives match the logged in user.
this quote is from a deprecated google documentation
But there is reasons to believe this is still true - even if the documentation above is deprecated.
You can observe this here - check out how they do it in this codelab https://github.com/firebase/functions-samples/blob/master/fcm-notifications/functions/index.js
and here
https://github.com/firebase/friendlychat-web/blob/master/cloud-functions/public/scripts/main.js
Since the getToken() is deprecated, use getInstanceId() to regenerate new token instead. It has same effect.
public static void resetInstanceId() {
new Thread(new Runnable() {
#Override
public void run() {
try {
FirebaseInstanceId.getInstance().deleteInstanceId();
FirebaseInstanceId.getInstance().getInstanceId();
Helper.log(TAG, "InstanceId removed and regenerated.");
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
Use this methods.
This is my solution, and I referred this at here
When you sign-up, use initFirebaseMessage,. and when log-out or delete
use removeFirebaseMessage().
private fun removeFirebaseMessage(){
CoroutineScope(Dispatchers.Default).launch {
FirebaseMessaging.getInstance().isAutoInitEnabled = false
FirebaseInstallations.getInstance().delete()
FirebaseMessaging.getInstance().deleteToken()
}
}
private fun initFirebaseMessage(){
val fcm = FirebaseMessaging.getInstance()
fcm.isAutoInitEnabled = true
fcm.subscribeToTopic("all")
fcm.subscribeToTopic("")
}
Another handy way to clear the firebase token and regenerated a new one using FirebaseMessaging.getInstance()
fun clearFirebaseToken() {
FirebaseMessaging.getInstance().apply {
deleteToken().addOnCompleteListener { it ->
Log.d("TAG++", "firebase token deleted ${it.result}")
token.addOnCompleteListener {
Log.d("TAG++", "firebase token generated ${it.result}")
if (it.result != null) saveTokenGenerated(it.result!!)
}
}
}
}
Just call deleteToken method on a background Thread upon Logout:
https://firebase.google.com/docs/reference/android/com/google/firebase/iid/FirebaseInstanceId.html#public-void-deletetoken-string-senderid,-string-scope
FirebaseInstanceId.getInstance().deleteToken(getString(R.string.gcm_defaultSenderId), "FCM")
The first argument takes the SenderID as it is defined in your FireBaseConsole
It takes a few seconds to update - and after that, you will no longer get FCM notifications.
I know I am late for the party. deleteInstanceId() should be called from the background thread since it's a blocking call. Just check the method deleteInstanceId() in FirebaseInstanceId() class.
#WorkerThread
public void deleteInstanceId() throws IOException {
if (Looper.getMainLooper() == Looper.myLooper()) {
throw new IOException("MAIN_THREAD");
} else {
String var1 = zzh();
this.zza(this.zzal.deleteInstanceId(var1));
this.zzl();
}
}
You can start an IntentService to delete the instance id and the data associated with it.
The firebase.iid package that contains FirebaseInstanceId is now deprecated. Auto-initialization has been migrated from Firebase Instance ID to Firebase Cloud Messaging. Also its behaviour has slighly changed. Before, a call to deleteInstanceId() would automatically generate a new token if auto-initialization was enabled. Now, the new token is only generated on the next app-start or if getToken() is called explicitly.
private suspend fun loginFCM() = withContext(Dispatchers.Default) {
val fcm = FirebaseMessaging.getInstance()
fcm.isAutoInitEnabled = true
fcm.token.await()
}
private suspend fun logoutFCM() = withContext(Dispatchers.Default) {
val fcm = FirebaseMessaging.getInstance()
fcm.isAutoInitEnabled = false // To prevent a new token to be generated automatically in the next app-start (remove if you don't care)
fcm.deleteToken().await()
}
If you want to logout completely from Firebase you can just delete the whole installation afterwards:
private suspend fun logoutFirebase() = withContext(Dispatchers.Default) {
logoutFCM()
val firebase = FirebaseInstallations.getInstance()
firebase.delete().await()
}
To wrap it all up, use background thread to delete the instanceID, the next time you login keep an eye on the Firestore/Realtime DB (if you save your tokens there), they will refresh
public void Logout() {
new Thread(){
#Override
public void run() {
super.run();
try {
FirebaseInstanceId.getInstance().deleteInstanceId();
FirebaseInstanceId.getInstance().getInstanceId();
} catch (final IOException e) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(Flags.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
}.start();
FirebaseMessaging.getInstance().setAutoInitEnabled(false);
FirebaseAuth.getInstance().signOut();
SharedPreferences sharedPreferences = getDefaultSharedPreferences(Flags.this);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.clear();
editor.apply();
startActivity(new Intent(Flags.this, MainActivity.class));
Flags.this.finish();
}
This code below I used it and it helps me, and I used Kotlin coroutine instead of Thread(Runnable{}).start() because it less cost than creating a new thread object
private fun logoutFromFCM() {
GlobalScope.launch(Dispatchers.IO) {
FirebaseInstallations.getInstance().delete()
FirebaseMessaging.getInstance().deleteToken()
FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
if (!task.isSuccessful) {
Log.w(TAG, "Fetching FCM registration token failed", task.exception)
return#OnCompleteListener
}
// Get new FCM registration token
val token = task.result
saveFirebaseToken(token)
Log.w(TAG, "Token Updated - newToken> $token")
})
}
}
For many situations where the notifications requirements are simple, the issue of handling log out can be implemented much more easily. For example, in my case every user is subscribed to only two topics:
Global alerts topic
User specific topic defined as the users email (with replacement of # with - because # is not allowed in topic string)
For such simple scenarios simply unsubscribe from the unwanted topics on log out:
Future<void> signOut() async {
messaging.unsubscribeFromTopic(emailToTopic(_firebaseAuth.currentUser.email));
await _firebaseAuth.signOut();
}
And of course subscribe to topics only on successful log in or sign up:
Future<String> signIn({String email, String password}) async {
try {
await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
messaging.subscribeToTopic(emailToTopic(email));
return "Signed in";
} on FirebaseAuthException catch (e) {
return e.message;
}
}
I have an android app with a login that sends login information over https to a java rest api that verifies the login credentials and then sends back a response stating whether the login was successful. My question is simple, what should I do to make sure the user doesn't have to login in again when they restart the app?
There are many ways to deal with one time login, it depends a lot on how the architecture is implemented on server side to make it work. Usually Login API are closely coupled for security reason. let me example what I mean by closely coupled.
As you want to Login in to Mobile App work once and the next time user opens the Mobile app you don't want to prompt user with SignIn screen again. and surely you don't want to save the confidential information like Username and Password on Mobile app as persistent data, as it can be fetched easily from android device. so what you do.
Lets assume you pass login credentials with a deviceID unique to the Android Device. Something like shown below. following is the JSON data sent to the LoginAPI
{
"username": "example#example.com",
"password": "it's not a secret",
"deviceId": "123456789"
}
Now as you don't want to save the Login credentials, server will generate a random alpha numeric String pass it to you in response every time you login to the Mobile App.
{
"Success": true,
"SuccessMessage": "credentials are correct, really!",
"ErrorMessage": null,
"Date": "dd/mm/yyyy",
"token": "1eghe4qha23aehraeh456789" // now this is a nasty String
}
you may now save the date and the token in Mobile App as persistent data.
So next time your user opens the app you may let user bypass the SignIn screen, and in background you can check if users token id is correct by sending that to the server, something like this. you may choose SharedPreferences or create a file and save it there
{
"API_TYPE": "login",
"deviceId": "123456789",
"token": "1eghe4qha23aehraeh456789"
}
Server may check this token id against the deviceID to check if this was the correct token for the device and respond.
You may ask why are we checking the token again as this was sent by the server in first place stating the credentials were correct. I agree you do have a point, lets say it is a fail safe condition, if the user changes the password from the website or something which causes to change the token on server for that user to change, if the server denies the token provided by you just ask the user to login again.
This will make sure that a user is logged in to only one Android Device at any given point of time.
You can store the credentials after the first login.
So when the user restart app, you can automatically make the request auth.
You can chose the best option to storage the credentials using the doc:
Data-Storage
This is simple, but maybe not the best way to do this.
I have the same problme,and I got a Json data from the server like this
{"error":0,"message":"ok","token":"7c75015e92e40511911e34752ee456e1","execute_time":"0.2723"}
so I keep the StuTokenin SharedPreferences,and when my app start,check the StuToken does it exist,like this
Map<String, String> loginInfo = InfoUtil.getLoginInfo(MainActivity.this);
if (loginInfo != null) {
if (loginInfo.get("StuToken") != null) {
getStuInfo(loginInfo.get("StuToken"));
Toast.makeText(MainActivity.this, "登录状态", Toast.LENGTH_SHORT).show();
} else {
initIntent(LoginActivity.class);
this.finish();
}
} else {
initIntent(LoginActivity.class);
this.finish();
}
}
hope that will works for you
You can use shared preference to store the values of the user and to check whether the user is already logged in or not. You can follow this Link.
Try out this code in your SplashScreen Activity.You can store a value in a sharedPrefence to check whether user is Logged in or not.
public class SplashActivity extends AppCompatActivity {
private static final long TIME_OUT_MILI = 3000;
private SharedPreferences mAppPreferences;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
mAppPreferences = AppUtil.getAppPreferences(this);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (mAppPreferences.getBoolean("is_Logged_in", false)) {
startActivity(new Intent(SplashActivity.this, MainActivity.class));
} else {
startActivity(new Intent(SplashActivity.this, LoginActivity.class));
}
finish();
}
}, TIME_OUT_MILI);
}
}
In Your LoginActivity's do this:
public class LoginActivity extends AppCompatActivity {
private SharedPreferences mAppPreferences;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
SharedPreferences.Editor editor = mAppPreferences.edit();
editor.putBoolean(Constants.SETTINGS_IS_LOGGED_IN, true);
editor.commit();
}
}
I am working with QuickBlox library for video chat. How can i manage it session?? because when i move to the next activity from the live chat activity i just lost the session because it says "Chat can't initialized" then i have to create the session again to do the calling. So what's the lifetime of quickblox session and how can i manage that.
I am also facing problem with recalling when stop the call or move to the next activity and try to recall i was not able to do that actually i tried different things so each time i am getting different errors. So if any one has experience with QuickBlox library need help here.
When i stop a call i call this function.
private void stopCall() {
//Toggle view show the smile view again
//ToggleSmileView();
try
{
cancelCallTimer();
if (videoChat != null) {
videoChat.stopCall();
videoChat = null;
}
if (videoChannel != null) {
videoChannel.close();
videoChannel = null;
}
sessionId = null;
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
and when i do the call i call this function
private void call() {
//toggle view
//ToggleSmileView();
// get opponent
//
VideoChatApplication app = (VideoChatApplication)getApplication();
opponent = new QBUser();
opponent.setId((app.getCurrentUser().getId() == VideoChatApplication.FIRST_USER_ID ? VideoChatApplication.SECOND_USER_ID : VideoChatApplication.FIRST_USER_ID));
// call
//
callTimer = new Timer();
callTimer.schedule(new CancelCallTimerTask(), 30 * 1000);
createSenderChannel();
initVideoChat();
if (videoChat != null)
{
videoChat.call(opponent, getCallType(), 3000);
//toggleMicrophoneMute();
}
else
{
logAndToast("Stop current chat before call");
}
}
For: Lifetime of quickblox session and how can i manage that.
To authenticate your application you have to set valid a auth_key and
generate a signature using your application auth_secret and receive a
session token which you should use to send requests to QuickBlox API
And,
Expiration time for token is 2 hours. Please, be aware about it. If
you will perform query with expired token - you will receive error
Required session does not exist.
Source: Authentication and Authorization Session Info
That part fits the Android sample code of creating the session,
QBAuth.createSession(new QBEntityCallbackImpl<QBSession>() {
#Override
public void onSuccess(QBSession session, Bundle params) {
Log.i(TAG, "session created, token = " + session.getToken());
}
#Override
public void onError(List<String> errors) {
}
});
Source: Android developers documentation
I have worked with the Android SDK, and feel it still needs some work, esp to reach a stage equivalent to the iOS SDK and REST API.
Though looking at your code, you should use getToken() before creating the new QBUser and related video chat calls, if the token has expired, just create a new one.
I have implemented similar code, not a video chat application, but in a general manner, write the functions in onSuccess() of session creation if the session needs to be recreated.
Fyi, for the multiple ones, you can try checking the error with the summary that has been given, categorized into 4; ..developers/Errors