Launcher Activity and Thread run() is called twice - java

My app is starting twice and the weird thing is, it depends on the LOAD_TIME which activity is called twice. With a long delay, like >5000ms, my Main Activity is called twice. As you can see in the snap shot, with 2000ms, my startup activity and my run() Thread is called twice.
It also only happens on my emulator, if I use my physical phone everything runs fine. I thought it might has something to do with the Consumer class, which requires a newer build version. But I think it requires 24 and I am using Nexus 5 with version 30 so I should be fine.
Ami doing something wrong with the lifecycle or threading?
public class StartUpActivity extends AppCompatActivity {
public final int LOAD_TIME = 2000;
public static int counter;
final Handler handler = new Handler(Looper.getMainLooper());
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
counter++;
Log.d("debug counter startup: ", counter+"");
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.activity_start_up);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.titel_bar);
handler.postDelayed(new Runnable() {
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public void run() {
Log.d("debug Handler: ", "run()");
PreLogin checkLoginStatus = new PreLogin();
checkLoginStatus.CheckIfStillLoggedIn((value) -> {
if(value==true){
Log.d("debug checkLogin", "checkIfStillLoggedIn=true");
Intent intent = new Intent(StartUpActivity.this, MainActivity.class);
intent.putExtra("caller", "StartUpActivity");
startActivity(intent);
finish();
}
else{
Log.d("debug checkLogin", "checkIfStillLoggedIn=false");
Intent intent = new Intent(StartUpActivity.this, ChooseLoginOrRegistrationActivity.class);
intent.putExtra("caller", "StartUpActivity");
startActivity(intent);
finish();
}
});
handler.removeCallbacks(null);
}
}, LOAD_TIME);
}
}
AndroidManifest:
<activity
android:name=".StartUpActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

Related

After calling the SplashScreenActivity the Application minimizes

I have the following Problem: I want to create a Splash Screen, that I can call during my Game Loop (it is a "Next-Level" splash screen).
When I call the Splash Screen, it works with animation and everything but the app minimizes itself after 5 seconds. This Splash Screen call happens after the main activity was already started.
My SplashActivity looks like this:
public class SplashActivity extends AppCompatActivity {
private ImageView logo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
logo = findViewById(R.id.logo);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
finish();
}
}, 5000);
Animation anim = AnimationUtils.loadAnimation(this, R.anim.viewanimation);
logo.startAnimation(anim);
}
}
And I want to call it in my GameLoop with the following call:
Intent i = new Intent(gamePanel.getContext(), SplashActivity.class);
gamePanel.getContext().startActivity(i);
The SplashScreen opens and the animation works, but then the MainActivity should be present again (not started new).
Try this one Splash.java
public class Splash extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
Thread myThread=new Thread(){
#Override
public void run() {
try {
Animation anim = AnimationUtils.loadAnimation(this, R.anim.viewanimation);
logo.startAnimation(anim);
//sleep time after animation
sleep(3000);
//to end the splash screen and call next activity with Intent
finish();
Intent intent = new Intent(Splash.this,MainActivity.class);
startActivity(intent);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
myThread.start();
}
}
In your manifest file, Splash.java will be your first activity to launch,
<activity android:name=".Splash">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Hope it helps.
using finishActivity() instead of finish().
finish() Call this when your activity is done and should be closed. The ActivityResult is propagated back to whoever launched you via onActivityResult().
finishActivity(int requestCode) is used to finish another activity that you had previously started with startActivityForResult(Intent, int)

How to stop JobService Scheduled to when app is removed from background?

Currently i am working with an application and my app has a feature that the user will be able to click on a Navigate button and my app will start the Google Map. Till now it's fine and i have done it. But the fact where i am stuck is that i want my app to perform some tasks. To achieve that i have used JobService and scheduled it to run after every 5 seconds even when the app is in background.
When the user presses the back button then inside onDestroy method i have cancelled the scheduler. But when the app is removed from the background by sliding or pressing the cross icon the JobService keeps running as the onDestroy method can be called or not by the os when it is removed from the background. How can i stop the scheduled job when the app is removed from the background?
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="javarank.com.serviceinbackground">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyJobService" android:exported="true" android:permission="android.permission.BIND_JOB_SERVICE" />
</application>
</manifest>
MyJobService class
public class MyJobService extends JobService {
#Override
public boolean onStartJob(final JobParameters jobParameters) {
Toast.makeText(getApplicationContext(), "Doing job", Toast.LENGTH_SHORT).show();
jobFinished(jobParameters, true);
return false;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
return false;
}
}
Here is my MainActivity
public class MainActivity extends AppCompatActivity {
private static final int JOB_ID = 1;
private JobInfo jobInfo;
private JobScheduler scheduler;
private Button navigateButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ComponentName componentName = new ComponentName(this, MyJobService.class);
JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, componentName);
builder.setPeriodic(5000);
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
// if true this job exists even after a system reboot...
builder.setPersisted(false);
jobInfo = builder.build();
scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
scheduler.schedule(jobInfo);
navigateButton = (Button) findViewById(R.id.navigate_button);
navigateButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
StringBuffer url = new StringBuffer("https://www.google.com/maps/dir/?api=1");
url.append("&origin=23.755736,90.374627");
url.append("&destination=23.754047,90.371682");
url.append("&travelmode=driving");
Uri gmmIntentUri = Uri.parse(url.toString());
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
mapIntent.setPackage("com.google.android.apps.maps");
startActivity(mapIntent);
}
});
}
#Override
protected void onDestroy() {
Toast.makeText(getApplicationContext(), "Destroy called.", Toast.LENGTH_SHORT).show();
scheduler.cancel(JOB_ID);
super.onDestroy();
}
}
I think you need to override following onStop() method and put stopService() command to stop the JobService.
#Override
protected void onStop() {
// A service can be "started" and/or "bound". In this case, it's "started" by this Activity
// and "bound" to the JobScheduler (also called "Scheduled" by the JobScheduler). This call
// to stopService() won't prevent scheduled jobs to be processed. However, failing
// to call stopService() would keep it alive indefinitely.
stopService(new Intent(this, MyJobService.class));
super.onStop();
}
You can create a new service like
MyService.java
public class MyService extends Service {
public MyService() {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
//stop you jobservice from here
stopSelf();
}
}
and start it from MainActivity.java
startService(new Intent(MainActivity.this,MyService.class));
Android> 7 automatically saves battery power. You must turn on the application's battery saving stop feature.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Intent intent = new Intent();
String packageName = getPackageName();
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent);
}
}
add this to AndroidManifest.xml
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
I faced this issue, but I found that after schedule job service, it can't be canceled (From view).
So I turned to stop it inside the job service by calling onStopJob(params)
and it worked.

When the splash screen of my Android application opens the application crashes

Initially, the first version of my app worked fine.
Later, after changing to the sidebar drawer application template, it does not function properly, crashing the application (due to the splash screen).
What could be the issue?
This is the code for the SpashScreen.java file:
public class SplashScreen extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash_screen);
Thread myThread = new Thread(){
#Override
public void run(){
try {
sleep(3000);
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
myThread.start();
}
}
This is the manifest:
<?xml version="1.0" encoding="utf-8"?>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/example"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".SplashScreen"
android:label="#string/example"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity"></activity>
</application>
Try this might help
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
}, 3000);
Try to use :
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(SplashScreen.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}, 3000);
This code don't create new Thread,
P.S. Android cannot start activity from another Thread (only form UI)
startActivity() need to be run in main thread. Using postDelay() of Hanlder class
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
Intent i = new Intent(SplashScreen.this, MainActivity.class);
startActivity(i);
finish();
}
}, 3000);
using handler can solve this do below code it will work for you
handler.postDelayed(
new Runnable() {
public void run() {
Intent intent = new Intent(youractivity.this, MainActivity.class);
startActivity(intent);
}
}, 3000);

NotificationListenerService sendBroadcast not working?

I'm trying for well over 10 hours now and I can't seem to think about anyhting else. I tried every possible example on the internet, but to no avail.
I have NotificationMonitor class extending NotificationListenerService and I wanted to send message from this service to main activity(and possible other activities and services in the future) using Intent mechanism. I post code below:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.testpackage.test">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".NotificationMonitor"
android:label="#string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
</application>
</manifest>
MainActivity.java
public class MainActivity extends Activity {
private TextView txtView;
private NotificationReceiver nReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtView = (TextView) findViewById(R.id.textView);
//create receiver
nReceiver = new NotificationReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.testpackage.test.NOTIFICATION_MONITOR");
registerReceiver(nReceiver,filter);
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(nReceiver);
}
public void buttonClicked(View v){
if(v.getId() == R.id.btnTestBroadcast){
//send test intent without category
Log.d("ActivityMain","Button clicked");
Intent i = new Intent("com.testpackage.test.NOTIFICATION_MONITOR");
sendBroadcast(i);
}
}
class NotificationReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Log.d("ActivityMain","Intent received: "+intent.getAction()+" has extra: "+intent.hasExtra("info"));
if (intent.hasCategory("com.testpackage.test.TEST_CATEGORY")) {
if (intent.hasExtra("info")) {
txtView.setText(intent.getStringExtra("info"));
}
}
}
}
}
NotificationMonitor.java
public class NotificationMonitor extends NotificationListenerService {
private NotificationMonitorReceiver receiver;
#Override
public void onCreate() {
super.onCreate();
receiver = new NotificationMonitorReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.testpackage.test.NOTIFICATION_MONITOR");
registerReceiver(receiver,filter);
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
//do something
sendInfo("notification posted");
}
#Override
public void onNotificationRemoved(StatusBarNotification sbn) {
//do something
sendInfo("notification removed");
}
#Override
public void onListenerConnected() {
//service created and listener connected
Log.d("NM","Listener connected!");
sendInfo("listener connected");
}
private void sendInfo(String info) {
Log.d("NM", "sendInfo called!");
Intent i = new Intent("com.testpackage.test.NOTIFICATION_MONITOR");
i.addCategory("com.testpackage.test.TEST_CATEGORY");
i.putExtra("info", info);
sendBroadcast(i);
}
class NotificationMonitorReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
//no categories intents get replied
Log.d("NM","Intent received: "+intent.getAction()+" has categories: "+(intent.getCategories()!=null));
if (intent.getCategories() == null) {
Intent i = new Intent("com.testpackage.test.NOTIFICATION_MONITOR");
i.addCategory("com.testpackage.test.TEST_CATEGORY");
sendBroadcast(i);
}
}
}
}
After running this app in debug mode of course I need to re-enable notification permissions, so when I do I see in logcat:
10-10 16:22:46.428 7330-7381/com.testpackage.test D/NM: Listener connected!
10-10 16:22:46.428 7330-7381/com.testpackage.test D/NM: sendInfo called!
well, I should receive broadcast in my application, shouldn't I?
After I click button:
10-10 16:22:57.607 7330-7330/com.testpackage.test D/ActivityMain: Button clicked
10-10 16:22:57.612 7330-7330/com.testpackage.test D/ActivityMain: Intent received: com.testpackage.test.NOTIFICATION_MONITOR has extra: false
10-10 16:22:57.619 7330-7330/com.testpackage.test D/NM: Intent received: com.testpackage.test.NOTIFICATION_MONITOR has categories: false
so the Intent is properly created and send from main activity, received back by the same activity and NotificationListenerService, has no categories so should get replied but nothing happens like when sendInfo method is called.
Please help, I have no other ideas about what might be wrong.
edit: I tested with regular services and of course Broadcasts are working just fine. Is there by chance any possibility that you just can't sendBroadcast from this particular extended service class?
Oficially, I'm a moron. Answer is: I didn't set up Category filter in IntentFilter and this is why I received zero properly sent intents from my class. So, long story short, to "fix" this mistake all one needs to do is add:
filter.addCategory("com.testpackage.test.TEST_CATEGORY");
and that's it. Thank you for your attention.

Running background service through shortcut

So I want to launch a service from a shortcut. I know that this is not possible to do directly, so I've set up a activity with the sole purpose of starting the service.
The aim of my service is to send an intent to another app and then 5 seconds later send another so I've used a CountDownTimer to do this.
However, when I launch the Activity that starts the service from the shortcut (this is getting confusing) it launches the apps UI. I don't want this, as I want it to be a background service.
What am I doing wrong. I've only just got into development, so it could be something obvious, but I've been battling with this for a few days now.
For some reason when I run it from the service it just launches the app straight away...
When I run it straight from the invisible activity it runs properly for the 1st 5 seconds fine and then loads the app...
I can't figure out why it's loading the app at all.
I've included as much info as I can that would be relevant.
Any help is appreciated!
My service:
public class Pop1_5Service extends IntentService {
public Pop1_5Service() {
super("Pop1_5Service");
}
#Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
new CountDownTimer(5000, 2500) {
public void onTick(long millisUntilFinished) {
Intent i = new Intent(INTENT_ACTION);
Bundle b = new Bundle();
b.putInt(BUNDLE_VERSION_CODE, 1);
b.putString(BUNDLE_STRING_NAME, "POP1");
b.putString(BUNDLE_STRING_VALUE, "1");
i.putExtra(BUNDLE_NAME, b);
sendBroadcast(i); }
public void onFinish() {
Intent i = new Intent(INTENT_ACTION);
Bundle b = new Bundle();
b.putInt(BUNDLE_VERSION_CODE, 1);
b.putString(BUNDLE_STRING_NAME, "POP1");
b.putString(BUNDLE_STRING_VALUE, "1");
i.putExtra(BUNDLE_NAME, b);
sendBroadcast(i); }
}
}.start();
}
}
Activity that launches service:
public class Pop1_5Activity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, Pop1_5Service.class);
startService(intent);
finish();
}
}
Subsection of Manifest:
<activity
android:name=".Pop1_5Activity"
android:theme="#android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".Pop1_5Service" />
And the 'Create a Shortcut' Activity:
public class CreateShortcutActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent shortcutintent = new Intent(this, Pop1_5Activity.class);
ShortcutIconResource iconResource = Intent.ShortcutIconResource.fromContext(this, R.drawable.ic_launcher);
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutintent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Pop1_5");
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);
setResult(RESULT_OK, intent);
finish();
}
}
From the look of things, it looks like CreateShortcutActivity does nothing.
Your LAUNCHER is Pop1_5Activity, so when the user presses the app icon, this Activity will run, and it launches the Service.
All the code you have showed us are "invisible", the two Activities finish() themselves, and the Service is a Service.
You might want to look at how your BroadcastReceiver handles your broadcast. For instance, does it create another Activity through PendingIntent? Is the Activity created invisible?
Maybe you should try creating a pending Service instead of pending Activity in the BroadcastReceiver.

Categories

Resources