where to initialize the ID from GCM? - android

I use GCM in my project.Where do I get an ID, so it is always available at all times? Here is my code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (!CloudMessaging.checkPlayServices(this)) {
return;
}
CloudMessaging.getInstance(this).setRegistrationListener(eventHandler);
}
"but if I turn aside and then expand Programmes at, then again will get ID." ->Possibly:
If I change my orientation, then again I get a new Id.

You can get your ID for GCM
if (m_gcm == null)
{
m_gcm = GoogleCloudMessaging.getInstance(m_context);
}
m_regid = m_gcm.register("Your project id from google api console");
Note : please do this network operation in background thread..

Use SharedPreferences to store your ID once you get a new one.
Steps required: (do this in your onCreate)
Check if you already have a valid GCM id in your SharedPreferences
If you already have one, use it.
Otherwise, request a new one and save it in your SharedPreferences.

Related

How to clean up and close app after being called through an intent

We have an app that has a function using the Android share facility. If a property listing is shared from the Rightmove app, our app takes that property and adds the details to our server-side database. When the app is launched normally (not through share) it checks for updates on launch.
The app does what it is supposed to do when launched normally and also when launched by sharing from the Rightmove app. Except in the latter case it continues to check for updates which is not supposed to do.
Here is the onCreate() method where all the relevant code resides:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Intent rightmove = getIntent();
String action = rightmove.getAction();
String type = rightmove.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
String rm_text = rightmove.getStringExtra(Intent.EXTRA_TEXT);
if (rm_text.startsWith("I found this property on the Rightmove")) {
String[] parts = rm_text.split("/");
String rm_code = parts[parts.length - 1];
new UpdateList().execute(rm_code);
} else {
Toast.makeText(this.getApplicationContext(), "Lets Delight only takes share information from the Rightmove app", Toast.LENGTH_LONG).show();
}
this.finish();
}
user = findViewById(R.id.user);
status = findViewById(R.id.status);
message = findViewById(R.id.message);
Button dman = findViewById(R.id.button_decision);
Button todo = findViewById(R.id.button_todo);
new Update(status).check(this);
}
The if block for dealing with the share ends with this.finish(); but the code continues after this and checks for updates. It must therefore draw a UI that is not required or used.
Is it a case that finish(); takes a while to complete and, whilst it is doing so, the code continues to execute or is something else happening here? Either way, what is the "correct" way to handle having share information sent to an app that just processes that share data without presenting a UI to the user?

Can not get Registration ID in Emulator

Hi I am running ADMMessenger sample application provided with SDK.
in which I am not able to get Registration ID in register() method of MainActivity.
Method is like this.
private void register()
{
final ADM adm = new ADM(this);
if (adm.isSupported())
{
if(adm.getRegistrationId() == null)
{
adm.startRegister();
} else {
// final MyServerMsgHandler srv = new MyServerMsgHandler();
// srv.registerAppInstance(getApplicationContext(), adm.getRegistrationId());
}
Log.v("log_tag","Reg_id:: "+adm.getRegistrationId());
}
}
in Log cat I am always getting Reg_id:: null
and onRegistrationError() method of SampleADMMessageHandler is calling.
and error at there is ERROR_SERVICE_NOT_AVAILABLE
I can not understand what is problem, please help me.
For the service to work correctly you need to be using the Kindle image (not a generic Android one) and also make sure you have logged into your account on the device (pull down the status bar at the top and ensure you have selected an account)

Login flow for Gigya in mobile app with custom login UI

I'm developing an Android app using Gigya to allow people to register using Facebook and Twitter; in parallel another developer is doing the same thing in iOS. We want to implement custom login UI.
The standard method uses Gigya's own UI and is documented here:
http://developers.gigya.com/035_Mobile_SDKs/020_Android#Logging_in_the_User
Beneath, it simply suggests:
If you wish to implement the graphic design by yourself, use the login method instead.
The standard login method calls a dedicated post-login callback with an onLogin(...) method and all subsequent flows are described as stemming from this event. The other login method calls a standard onGSResponse(...) callback; it's not clear how the response can be used to construct a user so I've set up my implementation to call socialize.getUserInfo. Attempts to call either method have resulted in lots of unusual errors.
As per the Gigya instructions I'm starting up with
mGSAPI = new GSAPI(GIGYA_APP_KEY, this);
mGSAPI.setAPIDomain("eu1.gigya.com");
in onCreate(...) (where GIGYA_APP_KEY is a value copied from our console). I'm calling setAPIDomain because we were getting an invalid data center error (albeit with a 500001 code, not a 301001 code!), which this has fixed.
Facebook login goes through the login flow as I'd expect and then comes back with error 400093 (which the docs tell me is an invalid API parameter, and has the message " Missing parameter: client_id").
Twitter login comes back with 206002, " Account Pending Verification", which seems to make sense; I then call
mGSAPI.sendRequest(
"getUserInfo",
null, //parameters
true, //use HTTPS
this, //the callback
null //a context object
);
and this gives me the error:
Missing required parameter: No secret or signature were provided. Request could not be verified.
The documentation for socialize.getUserInfo suggest a UID is required for web apps, but not for native ones. It mentions no other mandatory fields. I am a bit stuck ... shouldn't the GSAPI object be handling verification, as it's initialized with the API key?
I can give you some direction at a very high level for integrating GIGYA. (Code below is not verbatim) Hopefully it is somewhat helpful.
For a private Android app I had created a Manager object (GigyaManager) that maintained a singleton instance of the GSAPI object.
This singleton GigyaManager was initialized in my application object:
public static GigyaManager getInstance(String apiKey, Context context) {
mGSAPI = new GSAPI(apiKey, context);
}
My GigyaManager class also had a wrapper method for handling the login w/social services:
public void loginWithSocialService(GigyaSocialProvider provider, GSResponseListener listener) throws Exception {
// did the user attempt a social login, and bail out on the registration
// phase?
if (GigyaManager.getInstance().getGSAPI().getSession() != null) {
logout();
}
GSObject providerArgs = new GSObject();
providerArgs.put(GigyaManager.GIGYA_ARG_PROVIDER, provider.name().toLowerCase());
mGSAPI.login(providerArgs, listener, null);
}
This was fired from an onClick listener in a fragment that contained a "login" button:
GigyaManager.getInstance("appKey", getActivity()).loginWithSocialService(GigyaSocialProvider.FACEBOOK, this);
That fragment had to implement GSResponseListener that has the callbacks to deal with whether the login was successful or not:
#Override
public void onGSResponse(String method, GSResponse response, Object context) {
if (!method.equalsIgnoreCase("login") || response.getErrorCode() != 0) {
return;
}
GIGYAResponseWrapper resp = new GIGYAResponseWrapper(response.getResponseText());
// user is attached to login provider?
if (resp.isIsAttached()) {
// start some sort of loader or asynctask to get information about user account
// connected to GIGYA social login
Bundle args = new Bundle();
args.putString(ARG_UID, resp.getUid());
args.putString(ARG_UID_SIGNATURE, resp.getUidSignature());
args.putString(ARG_SIGNATURE_TIMESTAMP, resp.getSignatureTimestamp());
args.putString(ARG_SOCIAL_NICKNAME, resp.getNickname());
} else {
// login success, but this social account is not associated with anything in GIGYA
}
}

Custom Account authenticator. Cleanup after account is removed from device

Is there a way to get some kind of notification/broadcast/etc. when a custom account is removed from "Accounts & sync settings"?
The application I have can facilitate multiple users on a device (this is for a corporate use) and uses a single SQLite database. Say I create multiple users for my application on a device and populate database with data that is relevant only to those two users. My problem here is that if one of the user is removed from "Accounts & sync settings" I have no way to cleanup database and/or some external files on SD card.
I could duplicate user information in a redundant table and compare it with registered accounts and then removing user data from the database if user information in the table and Account[] array from AccountManager does not match. Feels dirty to me.
You have two options:
You can use the addOnAccountsUpdatedListener method of AccountManager to add a listener in the onCreate method of an Activity or Service -- make sure you remove the listener in your onDestroy method (i.e. do NOT use this in an endlessly running service) or the Context used to retrieve the AccountManager will never be garbage collected
The AccountsService will broadcast an intent with the action AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION every time an account is added, removed or changed which you can add a receiver for.
I didn't see a lot of examples on how people implement account cleanup, so I thought I would post my solution (really a variation of the accepted answer).
public class AccountAuthenticatorService extends Service {
private AccountManager _accountManager;
private Account[] _currentAccounts;
private OnAccountsUpdateListener _accountsUpdateListener = new OnAccountsUpdateListener() {
#Override
public void onAccountsUpdated(Account[] accounts) {
// NOTE: this is every account on the device (you may want to filter by type)
if(_currentAccounts == null){
_currentAccounts = accounts;
return;
}
for(Account currentAccount : _currentAccounts) {
boolean accountExists = false;
for (Account account : accounts) {
if(account.equals(currentAccount)){
accountExists = true;
break;
}
}
if(!accountExists){
// Take actions to clean up. Maybe send intent on Local Broadcast reciever
}
}
}
};
public AccountAuthenticatorService() {
}
#Override
public void onCreate() {
super.onCreate();
_accountManager = AccountManager.get(this);
// set to true so we get the current list of accounts right away.
_accountManager.addOnAccountsUpdatedListener(_accountsUpdateListener, new Handler(), true);
}
#Override
public void onDestroy() {
super.onDestroy();
_accountManager.removeOnAccountsUpdatedListener(_accountsUpdateListener);
}
#Override
public IBinder onBind(Intent intent) {
AccountAuthenticator authenticator = new AccountAuthenticator(this);
return authenticator.getIBinder();
}
}

Android - security through inheritence

I want to extend a common security check to nearly every view of my application. To do this, I have made this class
public class ProtectedActivity extends ActivityBase {
boolean isAuthenticated = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread validationThread = new Thread()
{
#Override
public void run()
{
try
{
isAuthenticated = UserService.validateToken();
}
catch (FTNIServiceException e)
{
//eat it
}
finally
{
if (!isAuthenticated)
{
startActivity(new Intent(ProtectedActivity.this, SignInActivity.class));
finish();
}
}
}
};
validationThread.start();
}
}
The logic is simple. Validate the user against my restful api to make sure they are signed in. If they aren't, show them to the signin page.
This works great, because to add the security check, all I need to do is inherit from my ProtectedActivity.
public class MainMenuActivity extends ProtectedActivity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
The problem is, however, that I periodically receive View not attached to window manager errors. I understand why this is happening. I am starting a new intent in the parent class, and the child lives on. to attempt to alter it's view even though a new intent has started. What is a better way to handle this so that if a user is not authenticated (such as their session expires serverside), it won't error when sending the user to the sign in screen?
Don't you Thread. Use AsyncTask instead which should handle your references to windows correctly.
On a different note, I would change this to a different implementation. Why don't use the Preferences storage on the phone to store some kind token. If the token is not valid then request a new token and all the stuff you are doing currently. This way is better because you don't want to request a REST call every time.
I imagine something like this (pseudo code)
Check if credentials exist in Preference
if(valid) then do nothing
else use AsyncTask and pop up a loader screen "Waiting..."

Categories

Resources