How to run code on Application opens in Android? - oncreate

My Android app need the user to create an account to be able to use the app. The account info is stored in SQLite database. When the application starts I check if the user has an account, if not I show a sign up activity for the user.
Now I get reports from users that they sometimes comes to the sign up activity even if they've already created an account. This happens when they've closed the application and reopen it again.
This is the code I'm using and I need to figure out what the problem might be:
//MyApplication.java
public class MyApplication extends Application {
private DataBaseUtility dbu;
public boolean hasAccount;
#Override
public void onCreate() {
super.onCreate();
//Init sqlite database
this.dbu = new DataBaseUtility(this);
//This loads the account data from the database and returns true if the user has already created an account
this.hasAccount = loadAccount();
}
public boolean loadAccount() {
boolean loadedData = false;
String query = "SELECT data FROM tblaccount WHERE tblaccount.deleted=0";
Cursor cursor = this.dbu.getCursor(query);
if (cursor != null) {
while (cursor.moveToNext()) {
loadedData = true;
}
cursor.close();
}
return loadedData;
}
}
//MainActivity.java
public class MainActivity extends TabActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MyApplication application = (MyApplication)getApplication();
if (!application.hasAccount) {
//Take the user to the sign up activity
}
}
My idea is that maybe sometimes MainActivity.onCreate() runs before MyApplication.onCreate(). Can that be the case?

In application's onCreate, you are checking if the user has an account and setting a boolean.
You are checking in the MainActivity's onCreate if the user has an account through the application's boolean.
application's onCreate() executing before MainActivity's onCreate() is always the case! It is impossible for a different execution path to occur and since application's onCreate() does not have a Runnable it is a 100% garantuee.
Please make sure you're DataBaseUtility does not have any Runnables.
Anyway STILL there are several ways to reproduce the error! I will not state these now but you can know them when you see:
SOLUTION
MainActivity You have forgotten to update application.hasAccount upon successfull sign up~
public class MainActivity extends TabActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MyApplication application = (MyApplication)getApplication();
if (!application.hasAccount) {
//Take the user to the sign up activity
//if(successful) application.hasAccount = true
}
}
To avoid database exceptions
I use this:
REMARK It would be much better to use more strong persistent status saving for the database -i.e. SharedPreferences
boolean isOpened = false;
//When I need to open
if(!isOpened){
//open
isOpened = true;
}
//When I need to close
if(isOpened){
//close
isOpened = false;
}
onDestroy() { //every onDestroy
if(isOpened){
//close
}
}

Related

Xamarin Android Share Link/Text via social media from custom renderer

I wan't to share a link via social media from custom renderer
public class CustomActions : ICustomActions
{
Context context = Android.App.Application.Context;
public void ShareThisLink()
{
Intent sharingInt = new Intent(Android.Content.Intent.ActionSend);
sharingInt.SetType("text/plain");
string shareBody = "https://www.google.com";
sharingInt.PutExtra(Android.Content.Intent.ExtraSubject, "Subject");
sharingInt.PutExtra(Android.Content.Intent.ExtraText, shareBody);
context.StartActivity(Intent.CreateChooser(sharingInt, "Share via"));
}
}
This error occur
Android.Util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
even when I added the below code I still get same error
sharingInt.AddFlags(ActivityFlags.NewTask);
The problem is that Intent.CreateChooser creates yet another Intent. What you want to do is to set the flag on this new intent:
public void ShareThisLink()
{
Intent sharingInt = new Intent(Android.Content.Intent.ActionSend);
sharingInt.SetType("text/plain");
string shareBody = "https://www.google.com";
sharingInt.PutExtra(Android.Content.Intent.ExtraSubject, "Subject");
sharingInt.PutExtra(Android.Content.Intent.ExtraText, shareBody);
var intent = Intent.CreateChooser(sharingInt, "Share via");
intent.AddFlags(ActivityFlags.NewTask);
context.StartActivity(intent);
}
Alternatively to avoid the need to do this, you could cache the MainActivity instance Xamarin.Forms uses:
public MainActivity
{
public static MainActivity Instance {get;private set;}
protected override void OnCreate(Bundle bundle)
{
Instance = this;
...
}
}
And then use the Instance as the Context in your code instead of the Application.Context

Cannot connect to google API client in Android Things

Here is my code
public class MainActivity extends Activity implements GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener {
private GoogleApiClient mGoogleApiClient;
private String TAG = "app comm";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int code = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext());
if (code == ConnectionResult.SUCCESS) {
Log.d(TAG, "success ");
buildGoogleApiClient();
} else {
Log.d(TAG, "fail ");
}
}
private void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Nearby.CONNECTIONS_API).addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.d(TAG,"connected");
}
#Override
public void onConnectionSuspended(int i) {
Log.d(TAG,"suspended");
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.d(TAG,"failed");
}
}
I am new to this
I run this program in raspberry pi 3
I have checked and internet is working.
isGoogleServicesAvailable is returning true.
but none of the override methods called. I don't know what I am missing.
Here is my log
Connected to process 8191 on device google-iot_rpi3-192.168.1.2:5555
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
I/zygote: Late-enabling -Xcheck:jni
W/zygote: Using default instruction set features for ARM CPU variant (generic) using conservative defaults
I/InstantRun: starting instant run server: is main process
V/first log: first raspberry log message
D/app comm: success
D/vndksupport: Loading /vendor/lib/hw/android.hardware.graphics.mapper#2.0-impl.so from current namespace instead of sphal namespace.
Looking at your code snippet, you are not calling the connect method after building it, which is what actually starts the connection and gives a callback.

How to use ranging in didRangeBeaconsInRegion

-------EDIT 2--------
Still using the post of Davidgyoung and these comments, now I have a FatalException :
E/AndroidRuntime﹕ FATAL EXCEPTION:
IntentService[BeaconIntentProcessor]
Process: databerries.beaconapp, PID: 19180
java.lang.NullPointerException
at databerries.beaconapp.MyApplicationName.didEnterRegion(MyApplicationName.java:76)
at org.altbeacon.beacon.BeaconIntentProcessor.onHandleIntent(BeaconIntentProcessor.java:83)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.os.HandlerThread.run(HandlerThread.java:61)
This error is due to the calling of setRangeNotifier()?
-------EDIT--------
After the post of Davidgyoung and these comments, I tried this method, but still not working :
public class MyApplicationName extends Application implements BootstrapNotifier {
private static final String TAG = ".MyApplicationName";
private RegionBootstrap regionBootstrap;
private BeaconManager beaconManager;
List region_list = new ArrayList();
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "App started up");
// wake up the app when any beacon is seen (you can specify specific id filers in the parameters below)
List region_list = myRegionList();
regionBootstrap = new RegionBootstrap(this, region_list);
BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
beaconManager.setBackgroundScanPeriod(3000l);
beaconManager.setBackgroundBetweenScanPeriod(5000l);
}
#Override
public void didDetermineStateForRegion(int arg0, Region arg1) {
// Don't care
}
#Override
public void didEnterRegion(Region region) {
Log.d(TAG, "Got a didEnterRegion call");
// This call to disable will make it so the activity below only gets launched the first time a beacon is seen (until the next time the app is launched)
// if you want the Activity to launch every single time beacons come into view, remove this call.
regionBootstrap.disable();
Intent intent = new Intent(this, MyActivity.class);
// IMPORTANT: in the AndroidManifest.xml definition of this activity, you must set android:launchMode="singleInstance" or you will get two instances
// created when a user launches the activity manually and it gets launched from here.
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
String zone = region.toString();
Log.d(TAG, "Enter in region");
String text = "Enter in " + zone;
Log.d(TAG, text);
String uuid = "UUID : " + region.getId1();
Log.d(TAG, uuid);
//This part is not working
beaconManager.setRangeNotifier(this);
beaconManager.startRangingBeaconsInRegion(region);
}
#Override
public void didExitRegion(Region arg0) {
// Don't care
}
The errors are about the input in setRangeNotifier and an exception for startRangingBeaconsInRegion
This isn't my main class, my main class :
public class MyActivity extends Activity{
public final static String EXTRA_MESSAGE = "com.example.myapp.MESSAGE";
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d("myActivity","onCreate");
}
}
I want all the IDs of the beacons in the region. With this method if I understand, the app is wake-up in the background when she detected a region and normally the "startRangingBeaconsInRegion" can give me a list of beacons with this one I can take the Ids.
-------Original--------
I would like to know all the beacon around me. I know the UUID of this beacons and I can get it with 'region.toString();'. But, I need the others id of the beacons. And, I don't have "Beacon" on didRangeBeaconsInRegion.
How to know the beacons in the region?
And last question, it's possible to make that in the background?
Thanks
You can see an example of ranging for beacons in the "Ranging Sample Code" section here: http://altbeacon.github.io/android-beacon-library/samples.html
This will allow you to read all the identifiers by looking at each Beacon object returned in the Collection<Beacon> beacons in the callback. Like this:
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
for (Beacon beacon: beacons) {
Log.i(TAG, "This beacon has identifiers:"+beacon.getId1()+", "+beacon.getId2()+", "+beacon.getId3());
}
}
Once you start ranging, it will continue to do so in the background, provided you don't exit the activity that starts the ranging. Under some uses of the library, ranging slows down in the background, but this only happens if using the BackgroundPowerSaver class. If you don't want ranging to slow down in the background, simply don't enable background power saving with the library.

Vaadin close UI of same user in another browser/tab/system

I'm doing a project in Vaadin 7. In that I need to implement something like below for the login.
A user 'A' is logged in to a system '1'. And again he logs into another system '2'. Now I want to know how to close the UI on the system '1'.
I tried something and can able to close the UI, If it is the same browser. But, for different systems/browser. I don't have any idea.
My Code:
private void closeUI(String attribute) {
for (UI ui : getSession().getUIs()) {
if(ui.getSession().getAttribute(attribute) != null)
if(ui.getSession().getAttribute(attribute).equals(attribute))
ui.close();
}
}
Can anyone help me in this?
I have a situation similar to your where I need to display several info regarding all sessions. What I did was I created my own Servlet extending the VaadinServlet with a static ConcurrentHashmap to save my sessions info, and a SessionDestroyListener to remove any info from the map upon logout. Initially I also had a SessionInitListener where I added the info in the hashmap but I realized I only had the user information after authentication so I moved this part to the page handling the login.
I guess you could do something similar, or at least this should get you started:
public class SessionInfoServlet extends VaadinServlet {
private static final ConcurrentHashMap<User, VaadinSession> userSessionInfo = new ConcurrentHashMap<>();
// this could be called after login to save the session info
public static void saveUserSessionInfo(User user, VaadinSession session) {
VaadinSession oldSession = userSessionInfo.get(user);
if(oldSession != null){
// close the old session
oldSession.close();
}
userSessionInfo.put(user, session);
}
public static Map<User, VaadinSession> getUserSessionInfos() {
// access the cache if we need to, otherwise useless and removable
return userSessionInfo;
}
#Override
protected void servletInitialized() throws ServletException {
super.servletInitialized();
// register our session destroy listener
SessionLifecycleListener sessionLifecycleListener = new SessionLifecycleListener();
getService().addSessionDestroyListener(sessionLifecycleListener);
}
private class SessionLifecycleListener implements SessionDestroyListener {
#Override
public void sessionDestroy(SessionDestroyEvent event) {
// remove saved session from cache, for the user that was stored in it
userSessionInfo.remove(event.getSession().getAttribute("user"));
}
}
}

Sterling database not persist on Windows phone

I followed sterling database examples from several persons. Neither of them seems to work out for me. When I persist some stuff on my database everything clearly gets persisted using sterling (on my phone, not emulator) when debugging. However when I relaunch my app the database is empty. Is somebody else experiencing the same problem. Or does someone have a complete working example. I know my serializing and saving works... As long as I don't relaunch my app loading my state works...
Code in my app.cs
public static ISterlingDatabaseInstance Database { get; private set; }
private static SterlingEngine _engine;
private static SterlingDefaultLogger _logger;
private void Application_Launching(object sender, LaunchingEventArgs e)
{
ActivateEngine();
}
// Code to execute when the application is activated (brought to foreground)
// This code will not execute when the application is first launched
private void Application_Activated(object sender, ActivatedEventArgs e)
{
ActivateEngine();
}
// Code to execute when the application is deactivated (sent to background)
// This code will not execute when the application is closing
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
DeactivateEngine();
}
// Code to execute when the application is closing (eg, user hit Back)
// This code will not execute when the application is deactivated
private void Application_Closing(object sender, ClosingEventArgs e)
{
DeactivateEngine();
}
private void ActivateEngine()
{
_engine = new SterlingEngine();
_logger = new SterlingDefaultLogger(SterlingLogLevel.Information);
_engine.Activate();
Database = _engine.SterlingDatabase.RegisterDatabase<SokobanDb>();
}
private void DeactivateEngine()
{
_logger.Detach();
_engine.Dispose();
Database = null;
_engine = null;
}
Code in my viewModel
public void LoadState(int level)
{
var levelState = App.Database.Load<LevelState>(level);
if (levelState != null)
{
//TODO: check if game started, then create board from boardstring property else create new board
//Labyrint = new Labyrint(Factory.CreateBoard());
NewGame(level);
}
else
{
NewGame(level);
}
}
public void SaveState()
{
var levelState = new LevelState { LevelId = _level, Moves = Labyrint.Moves, Board = Labyrint.ToString() };
App.Database.Save(levelState);
App.Database.Flush(); //Required to clean indexes etc.
}
The default Sterling database uses an in-memory driver. To persist, pass it an isolated storage driver. Per the documentation guide quickstart:
https://sites.google.com/site/sterlingdatabase/sterling-user-guide/getting-started
The code looks like this:
_databaseInstance = _engine.SterlingDatabase.RegisterDatabase(new IsolatedStorageDriver());
Note the instance of the isolated storage driver being passed in. That should do it for you.
When in doubt, take a look at the unit tests shipped with the source. Those contain tons of examples of memory, isolated storage, etc. to show various patterns for setting it up.

Resources