Libgdx Android: method onStart() not called after onCreate() - java

onStart()
I know that onStart() method is called after onCreate() ( via Activity Lifecycle documentation ), but in my LibGDX project this doesn't happen. I' ve this code:
#Override
protected void onStart()
{
super.onStart();
Gdx.app.debug(TAG, "onStart");
}
but the string in debug terminal appears only if I resume the app from background. I need to do stuff after the initialise of the activity, when it becomes visible.
EDIT: MORE CODE
public class AndroidLauncher extends AndroidApplication {
private final static String TAG = AndroidLauncher.class.getSimpleName();
GoogleResolver googleResolver;
GoogleSignInAccount acct;
private Preferences googlePrefs;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
googleResolver = new GoogleResolverAndroid();
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
config.useImmersiveMode = true;
config.useGyroscope = false;
config.useCompass = false;
config.useAccelerometer = false;
GoogleLoginHandler.getInstance().setContext(this.getContext());
GoogleLoginHandler.getInstance().startApiClient();
GameManager.getInstance().listener = googleResolver;
initialize(new MainCrucy(), config);
googlePrefs = Gdx.app.getPreferences(GOOGLE_PREF);
GoogleLoginHandler.getInstance().mGooglePrefs = Gdx.app.getPreferences(GOOGLE_PREF);
}
#Override
protected void onStart()
{
super.onStart();
Gdx.app.debug(TAG, "onStart");
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(GoogleLoginHandler.getInstance().getGoogleApiClient());
if (opr.isDone())
{
Gdx.app.debug(TAG, "Loggato");
GoogleSignInResult result = opr.get();
handleSignInResult(result);
} else {
opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
#Override
public void onResult(GoogleSignInResult googleSignInResult) {
handleSignInResult(googleSignInResult);
}
});
}
}
This is what I do. But onStart() does anything

How long do you wait after launching you application?
You have to remember that your app can take time to Start. If what you say is true than you wouldn't see Gdx debug - it's still fires at onStart().
So I assume:
you launch an app
you don't want to wait so you minimize that
you open it and onStart() ends and you see debug logs
By the way, could you show more code?
In the meantime look at the life cycle of Android app.
Android lifecycle

You can't use Gdx.app.debug() before the Libgdx application has had a chance to start up. I'm not positive if this happens before onStart() because libgdx doesn't run on the UI thread. Also, you must also use Gdx.app.setLogLevel(Application.LOG_DEBUG) first or calls to Gdx.app.debug() will do nothing.
But you can just use Android's Log.d() instead.

Related

Asynctask slow down issue

I'm trying to check existence of 2000 files in Asynctask.
In the initial execution, it works well.
But if I restart app about 10 times , loading speed slows down.
As I am a beginner developer, I lack understanding of Asynctask.
Please give me some advices.
This is my splash activity
public class SplashActivity extends AppCompatActivity {
getFirstData gfd;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
gfd = new getFirstData(this, (TextView) findViewById(R.id.textView18));
gfd.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, this);
}
#Override
protected void onDestroy() {
try
{
if (gfd.getStatus() == AsyncTask.Status.RUNNING)
{
gfd.cancel(true);
}
else
{
}
}
catch (Exception e)
{
}
super.onDestroy();
}
}
And this is my asynctask code
public class getFirstData extends AsyncTask<Context,Integer,Void> {
private PowerManager.WakeLock mWakeLock;
private Context context;
private TextView textview;
getFirstData(Context context,TextView tv){
this.context=context;
this.textview=tv;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
PowerManager pm = (PowerManager) this.context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
mWakeLock.acquire();
}
#Override
protected Void doInBackground(Context...contexts) {
Database.addDB();
for (int i = 0; i < Database.db_list.size(); i++) {
File filetemp = Database.getFilename(i, ".pdf", Database.db_list);
if (filetemp.exists()) {
Database.db_list.get(i).isDownloaded = true;
}
publishProgress(Database.db_list.size(),i);
}
return null;
}
#Override
protected void onProgressUpdate(Integer... params) {
super.onProgressUpdate(params);
textview.setText("Load("+params[1]*100/params[0]+"%)");
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
Intent intent = new Intent(this.context, MainActivity.class);
this.context.startActivity(intent);
((Activity)this.context).finish();
}
}
AsyncTask cancel method doesn't immediately stop your AsyncTask, instead it'll only 'cancel' after doInBackground completes. (Reference)
Calling this method will result in onCancelled(java.lang.Object) being invoked on the UI thread after doInBackground(java.lang.Object[]) returns. Calling this method guarantees that onPostExecute(Object) is never subsequently invoked, even if cancel returns false, but onPostExecute(Result) has not yet run. To finish the task as early as possible, check isCancelled() periodically from doInBackground(java.lang.Object[]).
If you want your AsyncTask to end as quickly as possible, just make a check every 10 (or whatever value you deem suitable) iterations. Something along the following lines should work.
#Override
protected Void doInBackground(Context...contexts) {
Database.addDB();
for (int i = 0; i < Database.db_list.size(); i++) {
File filetemp = Database.getFilename(i, ".pdf", Database.db_list);
if (filetemp.exists()) {
Database.db_list.get(i).isDownloaded = true;
}
publishProgress(Database.db_list.size(),i);
if (i%10==0 && isCancelled()) {
break;
}
}
return null;
}
I see you actually read the manual! Good work!
While its a good effort, unfortunately, the basic approach really just won't work.
I'm not completely clear on what is making the app slow down. If by "restart" you mean back-arrow and then start from the Desktop, then in is probably because you have many downloads running at once. Note that there is no way to stop your AsyncTask once you start it: cancel doesn't actually do anything, unless you implement it.
Your AsyncTask has all the typical problems with leaking a context (Studio is probably yelling at you about this already: pay attention). There is no reason to believe that the Activity that starts the task is still there when the task completes.
My suggestion is that you separate the state of the app from the Activity that views that state. This approach has lots of names but usually something like ViewModel. The View model is some kind of singleton that only allows users to see the Splash page until its state changes (it has the files downloaded). Then it shows the MainActivity.
Good luck!

How to start a FlutterActivity and change route

Im trying to make an alarm clock using flutter, and start the flutter activity with a path to the alarm ("/alarm" path). I have acccomplished starting the MainActivity using MethodChannels, but i need to somehow route to "/alarm", but calling getFlutterView().pushRoute("/alarm") does not do anything. The activity just starts in the main view instead of alarm route.
Thanks in advance!
I have managed to startActivity using MethodChannels, but when calling getFlutterView().pushRoute("/alarm") in onCreate, it does not change the route.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
// This does not change the route (setInitialRoute doesn't work either)
getFlutterView().pushRoute("/alarm");
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
new MethodCallHandler() {
#Override
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("setAlarm")) {
// pushRoute works here, but not in onCreate
getFlutterView().pushRoute("/alarm");
} else {
result.notImplemented();
}
}
}
);
}
Expected results: Change the route to "/alarm"
Actual results: Nothing happens, the activity gets opened on initial route eg. the main page
Found the solution,
pushRoute() or setInitialRoute() doesn't work until the View has been inflated.
Here is the code that works:
FlutterView.FirstFrameListener mListener = new FlutterView.FirstFrameListener() {
#Override
public void onFirstFrame() {
getFlutterView().pushRoute("/alarm");
}
};
getFlutterView().addFirstFrameListener(mListener);

How to send event from MainActivity onCreate to React Native?

I'm working on an alarm clock and I can't figure out how to sendEvent to React Native from MainActivity. This is what I managed to do so far:
#Override
protected void onCreate(Bundle savedInstanceState) {
mInitialProps = new Bundle();
final Bundle bundle = mActivity.getIntent().getExtras();
ReactInstanceManager mReactInstanceManager = getReactNativeHost().getReactInstanceManager();
ReactApplicationContext context = (ReactApplicationContext) mReactInstanceManager.getCurrentReactContext();
if (context == null) {
mReactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
public void onReactContextInitialized(ReactContext context) {
if (bundle != null && bundle.containsKey("sendAlarm")) {
if (bundle.getString("sendAlarm").equals("sendAlarmOn")) {
LauncherModule.startAlarm(mActivity); // works
LauncherModule.sendAlarmEvent(); // doesn't work. Should run after alarm manager starts app which previously had been killed
}
}
}
});
} else {
if (bundle != null && bundle.containsKey("sendAlarm")) {
if (bundle.getString("sendAlarm").equals("sendAlarmOn")) {
LauncherModule.startAlarm(mActivity); // works
LauncherModule.sendAlarmEvent(); // works and sends event only when app was left open
}
}
}
super.onCreate(savedInstanceState);
}
The code works only If app is left open and alarm manager restarts app itself. If I close the app and alarm manager starts it then it seems that only startAlarm function (it has sound effect) is beeing triggered..
No matter what I do whether I put sendEvent function inside Mainactivity or elsewhere (e.g. external module) it simply won't send event if I close the app. I also tried getReactInstanceManager().getCurrentReactContext() combined with while from this question Send data from Android activity to React Native to no avail.
Also tried to create bolean beeing set to true onCreate and then send event onStart or onRestart. Also to no avail.
Any suggestions?
EDIT: Here is how sendEvent function looks like:
public final void sendEvent(String eventName, boolean isAlarmOn) {
getReactInstanceManager().getCurrentReactContext()
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, isAlarmOn);
}
SOLUTION
Well I think that the answer is not to use sendEvent method onCreate because (I might be wrong) listener seems to be initialized after the event had been sent. So nothing is going to listen to this event.
It seems to work pretty well inside onStart, onRestart, onPause though.
What can we do? React Native provides ReactActivityDelegate with initial props. And it does the job!
ReactActivityDelegate in MainActivity should look as below:
public class ActivityDelegate extends ReactActivityDelegate {
private Bundle mInitialProps = null;
private final #Nullable Activity mActivity;
public ActivityDelegate(Activity activity, String mainComponentName) {
super(activity, mainComponentName);
this.mActivity = activity;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
mInitialProps = new Bundle();
final Bundle bundle = mActivity.getIntent().getExtras();
if (bundle != null && bundle.containsKey("sendAlarm")) {
if (bundle.getString("sendAlarm").equals("sendAlarmOn")) {
mInitialProps.putBoolean("alarmOn", true);
}
}
super.onCreate(savedInstanceState);
}
#Override
protected Bundle getLaunchOptions() {
return mInitialProps;
}
};
#Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new ActivityDelegate(this, getMainComponentName());
}
Then in your main app component (usually index.android.js) call your propTypes and use them to run your code:
static propTypes = {
alarmOn: PropTypes.boolean
}
componentDidMount() {
if (this.props.alarmOn === true) {
// your code
}
}
Voila!
You can find full example here: https://github.com/vasyl91/react-native-android-alarms

Handle calls of onStart and onStop only from outside my app

I want to make a cloud synchronization everytime my app is brought to front and a second time if the app disappears in background.
So I overwrote the onStart and onStop event methods of my activity:
#Override
protected void onStart() {
super.onStart();
doSync();
}
#Override
protected void onStop() {
doSync();
super.onStop();
}
Ok, that works fine for me but I found out that these methods are also called if I start a new activity (f.e. SettingsActivity.class) within my app (onStop) and come back to the main activity (onStart).
Is there a good way to ignore the calls of my own activities and only react on calls from "outside", f.e. I only want to synchronize if the user stops the app by pressing the home button and I also want to synchronize only if the user returns to the app by starting it from the app dreawer or app switcher?
+++ SOLUTION +++
Now I found a solution for my problem and I want to share it. Maybe it's not the best way because it's no SDK-based functionality but it works and it's quite simple.
I declared a flag, set it to false when the activity is created. Everytime I start another activity in the same app, I will set the flag to true and check its state in onPause and onResume.
public class MainActivity extends Activity {
private boolean transition;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
transition = false;
}
private void startSettingsActivity() {
transition = true;
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
}
private void doSync() {
// all steps for the cloud synchronization
}
#Override
protected void onResume() {
super.onResume();
if (!transition) {
// this is the case the user returns from
// the app drawer or app switcher or starts
// the app for the first time, so do sync
doSync();
} else {
// this is the case the user returns from another
// activity, so don't sync but reset the flag
transition = false;
}
}
#Override
protected void onPause() {
if (!transition) {
// this is the case the user presses the home button or
// navigate back (leaves the app), so do final sync
doSync();
} else {
// this is the case the user starts another activity, but
// stays in the app, so do nothing
}
super.onPause();
}
}

How to make `onResume` only be called when the activity comes to screen and not by other methods calling it

I have a situation with onResume() method and I don't know how to solve it.
conssider the following code:
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle b) {
super.onCreate(b);
Log.d("tag", "onCreate");
}
#Override
protected void onResume() {
super.onResume();
//do something only when everytime the activity comes to screen
Log.d("tag", "onResume");
}
private void myMethod() {
this.onResume();
}
}
If we asume that myMethod will definitly be called, I don't want to let onResume() to execute //do something only when everytime the activity comes to screen. I should note that myMethod is a fixed method and cannot be changed.
PS:The reason that I am asking this question is that I have a simillar situation with PermissionDispatcher library with android 6 and I want to call a "risky permission" in the onReume() method but if the user denies the permission, it will call the onReume() again, and since the permission required task is in the onResume(), the permission will be denied again and cauases an inifite loop
could anyone give me a suggestion?
UPDATE: here is the permissionDispatcher library and the issue that is related to my problem
verify this method Already Executed or not simply in if Condition
Bool a=true;
#Override
protected void onResume() {
super.onResume();
//do something only when everytime the activity comes to screen
if(a==true)
{
//your Actions
}
else if(a==false)
{
//do nothing
}
}
Use SharedPreferences in onResume
#Override
protected void onResume() {
super.onResume();
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
boolean firstStart = settings.getBoolean("firstStart", true);
if(firstStart) {
//do something only when everytime the activity comes to screen
Log.d("tag", "onResume");
//display your Message here
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("firstStart", false);
editor.commit();
}
}

Categories

Resources