I am using below code.
import android.app.Activity;
import android.os.Bundle;
import android.provider.ContactsContract.Data;
import android.util.Log;
public class ActivityDemoActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Thread(new Runnable() {
#Override
public void run() {
int i=0;
while(true){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.i("DATA", "Data.CONTENT_TYPE......"+(i++));
}
}
}).start();
}
#Override
public void onBackPressed(){
finish();
}
}
When I press Back button of device still thread is working in background.
My questions are...
when thread will stop?
Then why we required services in android?
Thank You.
Answers:
1 - it will stop after 100 milliseconds
2 - you need something to work in the background like a service that wakes up and
performs a function without there being a user to initiate it. Or you want to have
a progressDialog that tells the user some work is happening rather than let the user
assume the UI is frozen. Without the background service, your UI is left with an app
that doesn't respond while the work is happening.
Services are basically used for performing long-running application on the background.If you are using any network operations or playing musing or something like that, services are very much helpful..
Related
I am making an app that gives the user a notification when it is time for a monster egg to be hatched again. Up to 10 eggs can be hatched per day every 5 minutes. I thought I'd make a service that keeps a track of how much time has passed, but every time MainActivity closes on the emulator the service stops and calls onDestroy(). I made a test service to see if I could get the service to display log messages, or do something when onDestroy() is called. I was able to get the service to run a thread in onDestroy(), but obviously this is dangerous if I were to implement it.
I was also reading around the site and notice people recommend either Handler or Alarm Manager. Should I use these instead of service? And could someone also explain why my service stops when MainActivity is destroyed? Also would it be recommended to retrieve/store data from app preferences within this service or whatever class I end up using so that the service and MainActivity can talk to each other? Like for example a seed based on whenever the timer is up so that MainActivity can create an egg from the seed whenever it is started?
(edit)oops almost forgot: I also need it so that notifications appear whenever an egg is ready to hatch and whenever another batch of eggs is ready for the day. Whenever the user starts the app, the app should also display how long is left for another egg or another batch if the user has already used up their eggs for the day. Figured this context was important in determining whether I should use a service, alarm manager, or handler.
import android.app.Service;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
public class egg_notifications extends Service {
public static int time = -1;
public egg_notifications() {
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
AsyncTask datatask = new AsyncTask() {
#Override
protected Object doInBackground(Object[] objects) {
for(int c=0;c<300;c++){
Log.i("d","Time is "+c);
try {
Thread.sleep(1000);
} catch (Exception e) { }
}
return null;
}
}.execute();
return Service.START_STICKY;
}
#Override
public void onDestroy() {
Log.i("d","Service onDestroy");
AsyncTask datatask = new AsyncTask() {
#Override
protected Object doInBackground(Object[] objects) {
for(int c=0;c<300;c++){
Log.i("d","Time is "+c);
try {
Thread.sleep(1000);
} catch (Exception e) { }
}
return null;
}
}.execute();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Services end after 2 minutes in modern Android. If you just need a 5 minute timer, use an Alarm and AlarmManager to set one.
Why i can't force Android ANR with this code?
No log messages or pop up. The application is just launched lazily.
[UPDATE]
I can't get it even sleeping a View.setOnClickListener or BroadcastReceiver.onReceive!
Is there a trick?
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Log.e("Test", "", e);
}
}
}
I'm using Samsung GT-6200L with stock Android 3.2
Try it in onTouchEvent. In onCreate your activity is not fully running
#Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG,"onTouchEvent");
while(true) {}
}
The ANR-WatchDog project has a test app that produces ANRs in a reliable manner (as reliable as ANRs can be): the app hangs because of a deadlock.
The gist of it:
Prepare a lock object as a private field in your activity:
final Object mutex = new Object();
Have a thread that performs some work in a critical section, and an android.os.Handler that posts work depending on the same lock.
new Thread(new Runnable() {
#Override
public void run() {
synchronized (mutex) {
while (true) {
try {
Thread.sleep(60000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
synchronized (mutex) {
// Shouldn't happen
throw new IllegalStateException();
}
}
}, 1000);
Putting the above code snippet inside a button click handler, for example, should do the trick.
I've been facing the same issue yesterday, and I've found out that using a plain debug build ANR dialogs simply won't show up. (Although the UI thread was completely hanged.)
But after exporting and properly signing the application the dialogs were popped up properly (in every cases mentioned above). However I am still not sure what really prevents to pop up ANR messages, maybe someone else can clarify this later...
Try using:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int a=0;
while(true) {
a++;
}
}
Your code probably didn't work because it got setup too early, and the Activity probably wasn't fully initialized and created yet. With the above code, launch the activity and touch/swipe on the screen and wait for the ANR dialog to popup.
Make a button in your activity.
public void onBtn1(View v) {
int a = 0;
while(true) {
a++;
}
}
Make the button execute the above code.
Spam click the button with your finger =)
I used this code for force ANR
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void force(View view){
while(true) {}
}
I just created a simple button in the xml file and set android:onClick=force
So, I have a login screen. Upon pressing the 'Login' Button a JDBC Connection is made to check the username and password and then move onto the next Activity if the details are correct. As a result of this, the UI hangs for approximately 5 second. I assumed that this was because the connection was created in the same Thread, so I created a new one. I then created a Handler to interact with the UI depending on what happened with this connection.
The trouble is, the UI still hangs. Below is where the new Runnable is declared in the Activity (h is the custom Handler reference belonging to this Activity);
logInButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
progress.setVisibility(ProgressBar.VISIBLE);
new LoginProcessor(h).run(); // HERE!
}});
Below is the run() method from the LoginProcessor Runnable which includes the code that is causing the hang. The MicroManager class contains simple JDBC database interactions and makes the connection (nothing exciting in there really and I am trying to keep this as short as possible);
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
try{
MicroManager manager = new MicroManager(); // THIS LINE, AND THE LINE BELOW, ARE CAUSING THE HANG!!!!
if(manager.getEmployeeId(h.getLoginName(), h.getPassword())!= 0){
h.sendEmptyMessage(0);
}
}catch(Exception ex){
ex.printStackTrace();
h.sendEmptyMessage(1);
}
}
In the above, there is no direct interaction with the UI. Information is simply sent to the Handler so that it can do it on the UI thread. Lastly, here are the methods of my custom Handler called LogInHandler;
#Override
public void handleMessage(Message msg){
if(msg.what == 0){
activity.startActivity(new Intent(activity, AdvisorsPanelActivity.class));
activity.finish();
}else{
AlertDialog alertDialog = new AlertDialog.Builder(activity).create();
alertDialog.setTitle("Not Working");
alertDialog.show();
activity.setProgressVisible(ProgressBar.GONE);
}
}
public String getLoginName(){
return activity.getLoginName();
}
public String getPassword(){
return activity.getPassword();
}
Sorry to dump so much code on your guys, but I didn't think a complete picture was possible without all the above. I've trimmed it down as much as I can. I've only recently started working with Threading AND Android, so please be gentle with me.
Based on my experience: Use AsyncTask for JDBC and you shall torture no more.
EDIT :
This is a neat example of implementing AsyncTask:
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.System;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;
public class AsyncTaskActivity extends Activity implements OnClickListener {
Button btn;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button) findViewById(R.id.button1);
// because we implement OnClickListener we only have to pass "this"
// (much easier)
btn.setOnClickListener(this);
}
public void onClick(View view) {
// detect the view that was "clicked"
switch (view.getId()) {
case R.id.button1:
new LongOperation().execute("");
break;
}
}
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "Executed";
}
#Override
protected void onPostExecute(String result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed"); // txt.setText(result);
// might want to change "executed" for the returned string passed
// into onPostExecute() but that is upto you
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}
}
You may want to create and handle your JDBC connection in
doInBackground(String... params) part of your code.
Good Luck.
So I've just noticed that my app is skipping quite a few frames when running in the emulator. This is my first app and I did some reading on the topic and found that I might not be starting the activities correctly. However, my activities are loaded through the settings menu and I don't know where this is in my code. If this is a big issue it would be appreciated if someone could point me in the right direction in relation to my specific code?
https://github.com/addrum/Calculate
I can post code here in preference if needed.
Edit: It appears to skip frames on the splash activity:
package com.main.androidcalculator;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class SplashActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
Thread timer = new Thread() {
public void run() {
try{
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
Intent openMain = new Intent("com.main.androidcalculator.MAINACTIVITY");
startActivity(openMain);
}
}
};
timer.start();
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
finish();
}
}
I think the emulator is just too slow.
Your code works fine on a real device. I've tested on GS3.
Maybe ProgressBar is just too heavy for the emulator.
The view has animation and a lot of stuffs.
(Remove the ProgressBar and the issue's gone!)
See also:
Choreographer(639): Skipped 50 frames
I'm writing an app that allows me to send a command through TCP/IP by clicking a button. However when I click to the button in the emulator it comes back with a message saying the button has stopped working. I was wondering if anyone could spot the error in my code.
CODE:
package button.test;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
public class ButtonActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void onClick(View view) throws UnknownHostException, IOException
{
Socket socket = new Socket("192.168.2.92", 60128);
try{
dataOutputStream.Object BUFFER = null;
write(BUFFER);
String buffer="ISCP000000100000000701000000!1PWR010D";
OutputStream os=socket.getOutputStream();
os.write(buffer.getBytes());
} catch(IOException e)
{
//error code
}
}
private void write(Object BUFFER) {
// TODO Auto-generated method stub
}
}
1. You missed declaring the button, and initializing it...
Eg:
public class ButtonActivity extends Activity {
Button mbutt;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mbutt = (Button)findViewById(R.id.Button_Click);
}
- Make a note that you must initialize the views only after the setContentView(), else your views won't get the id and will make your App to crash.
2. Its always advisable to keep the UI work on UI thread, and Non-UI work on Non-UI thread, but that became a law with the arrival of HoneyComb android version.
3. You can use Thread with a Handler to sync UI and Non-UI thread.
4. AsyncTask which is known as Painless Threading was introduced specially in android for this.
See this link for tutorials on Threads, Handlers and AsyncTask:
http://www.vogella.com/articles/AndroidPerformance/article.html
It looks like the socket connection work is taking a long time. Suggest putting this functionality inside an AsyncTask.
You haven't declared your button in onCreate()
You don't need to declare the button if you are inflating an xml.
Your problem is that you run a Network connectivity on a main Thread which is not allowed since api 11. Use a asynctask or a thread for this.
e.g.
new Thread() {
public void run() {
Socket socket = new Socket("192.168.2.92", 60128);
try{
dataOutputStream.Object BUFFER = null;
write(BUFFER);
String buffer="ISCP000000100000000701000000!1PWR010D";
OutputStream os=socket.getOutputStream();
os.write(buffer.getBytes());
} catch(IOException e)
{
//error code
}
}
}.start();