I am developing an XMPP chat client.I am using Background service to connect to network XMPP server.however when i start the server it gives Network on UI thread Exception.
when i downgrade the Android SDK to 8 it gives ANR exception
I tried starting the Service from onCreate method of the SPlash screen.
Runnable runnable = new Runnable() {
#Override
public void run() {
Intent serviceIntent=new Intent();
serviceIntent.setClass(getApplicationContext(), SeetiService.class);
startService(serviceIntent);
}
};
new Thread(runnable).start();
Thread serviceThread=new Thread()
{
public void run()
{
Intent serviceIntent=new Intent();
serviceIntent.setClass(getApplicationContext(), SeetiService.class);
startService(serviceIntent);
}
};
serviceThread.start();
But i still get the Same network on Main UI thread.
Can some one help?
Thanks
It seems that you are trying to start two Service simultaneously.AFAIK You can not start it with above piece of code.But i will show why you are facing ANR.
Intent serviceIntent=new Intent();
serviceIntent.setClass(getApplicationContext(), SeetiService.class);
startService(serviceIntent);
The above code is supposed to run on UI thread.and if you want to run it from another thread you must embedd it into runOnUiThread.So your block should look like.
Runnable runnable = new Runnable()
{#Override
public void run()
{
runOnUiThread(new Runnable()
{
public void run()
{
Intent serviceIntent = new Intent();
serviceIntent.setClass(getApplicationContext(), SeetiService.class);
startService(serviceIntent);
}
});
}
};
new Thread(runnable).start();
Related
I need to make so backround job without blocking user UI, so I made a test IntentService to check how it's work, but this intent services block the UI.
Here my Code on start app ic start service:
Intent msgIntent = new Intent(this, AutoExchange.class);
startService(msgIntent);
AutoExchange.java
public class AutoExchange extends IntentService{
public AutoExchange() {
super("AutoExchange");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The problem is that this service block the main Ui, somethig I did wrong?
instead of thread.sleep() you can you handler
here is an example
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// do stuff
}
},3000);
Try to make a new Runnable() around the try-catch-block.
Caution: A service runs in the main thread of its hosting process; the service does not create its own thread and does not run in a separate process unless you specify otherwise.
Source
Register your service in android manifest.
I am new to Android.
I am having Accelerometer sensor data in one activity. I stopped the SensorManager after a shake has been detected. Now I need to restart the activity automatically after 5 seconds, the SensorManager has stopped. Is it possible?
or is it possible to start the current activity from the same?
Can somebody help me with this?
Thanks in Advance :)
I need to restart the activity automatically after 5 seconds, the
sensorManager has stopped. Is it possible?
Yes it is possible using AlarmManager
When stopping SensorManager provide PendingIntent of Activity to AlarmManager with required delay to start Activity:
Intent intent = new Intent(context,MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context,0, intent,
Intent.FLAG_ACTIVITY_NEW_TASK);
AlarmManager manager =(AlarmManager) getSystemService(Context.ALARM_SERVICE);
manager.set(AlarmManager.RTC,System.currentTimeMillis() + 6000, pendingIntent);
Use this code when SensorManager has stopped. It will restart the Activity after 5 sec when SensorManager has stopped.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent intent = getIntent();
finish();
startActivity(intent);
}
}, 5000);
When you stop Sensor, you can start Activity after 5s by use Handler like
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
startActivity(...);
}
}, 5000);
Thread is used to provide delay.
Add the below code when your sensor stopped detected.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//Start Activity here
}
},5000);
I use Volley library to connect with server in my app. Now, I have to send request in background every 5 minutes also when app is not running (killed by user). How should I do it? With background services, AlarmManager (Google says that it isn't good choice for network operations) or something else?
Or maybe SyncAdapter will be good for it?
You can use a TimerTask with scheduleAtFixedRate in a service class to achieve this, here is an example of Service class, you can use it
public class ScheduledService extends Service
{
private Timer timer = new Timer();
#Override
public IBinder onBind(Intent intent)
{
return null;
}
#Override
public void onCreate()
{
super.onCreate();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
sendRequestToServer(); //Your code here
}
}, 0, 5*60*1000);//5 Minutes
}
#Override
public void onDestroy()
{
super.onDestroy();
}
}
You can use sendRequestToServer method to connect with the server.
Here is the manifest declaration of the Service.
<service android:name=".ScheduledService" android:icon="#drawable/icon" android:label="#string/app_name" android:enabled="true"/>
To start the service from MainActivity,
// use this to start and trigger a service
Intent i= new Intent(context, ScheduledService.class);
context.startService(i);
I prefer to use Android Handler because it is executes in UI Thread by default.
import android.os.Handler;
// Create the Handler object (on the main thread by default)
Handler handler = new Handler();
// Define the code block to be executed
private Runnable runnableCode = new Runnable() {
#Override
public void run() {
sendVolleyRequestToServer(); // Volley Request
// Repeat this the same runnable code block again another 2 seconds
handler.postDelayed(runnableCode, 2000);
}
};
// Start the initial runnable task by posting through the handler
handler.post(runnableCode);
I have two Bounded Services, and some Activities that bind themselves to the services when they need it.
The problem is the performance of the app is slow when the activities write the information got from the services in the display.
Android's documentation says about the Stated Services:
Caution: A services runs in the same process as the application in
which it is declared and in the main thread of that application, by
default. So, if your service performs intensive or blocking operations
while the user interacts with an activity from the same application,
the service will slow down activity performance. To avoid impacting
application performance, you should start a new thread inside the
service.
But it says nothing about the Bound Services running in other threads. So i decided to start the services in this way:
private void startRunService()
{
final Intent intent = new Intent(this, RunService.class);
Thread thread = new Thread(new Runnable() {
public void run() {
startService(intent);
}
});
thread.start();
}
private void startLinkerRunService()
{
final Intent intent = new Intent(this, LinkerRunService.class);
Thread thread = new Thread(new Runnable() {
public void run() {
startService(intent);
}
});
thread.start();
}
So starting each service in a different service I got an unexpected improvement of the performance. But I'm not sure that it is a good idea.
Do you know if it has side effects?
Thanks in advance.
I found some info about how to access the context from the subclass and also some info about
runOnUiThread(new Runnable() {
public void run() {
// Do something
}
});
But in my case it does not work. The application is still running, but the activity is maybe already destroyed. The first (main) activity is the parent activity of the one where my TimerTask is created. My code:
TimerTask tt = new TimerTask() {
#Override
public void run() {
// do something (cut)
// and at the end show info
getParent().runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getParent(),
getResources().getString(R.string.st_toast_msg_stopped),
Toast.LENGTH_LONG).show();
}
});
}
};
curTimer.schedule(tt, millisecondsUntilStop);
There is no error/ exception at log. But the toasted message is not shown. :-(
Now I have no Idea what I can else do/ try. I hope someone of you can help me.
P.S.: Maybe I use the wrong context? But I tried also some other context like the Context of the current activity, the ApplicationContext, ... .
Well you are using the wrong context here that is getParent(). Instead of using getParent() try to use the current_Activity.this like this,
TimerTask tt = new TimerTask() {
#Override
public void run() {
// do something (cut)
// and at the end show info
Activity_name.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(Activity_name.this,
getResources().getString(R.string.st_toast_msg_stopped),
Toast.LENGTH_LONG).show();
}
});
}
};
Rather than using a TimerTask, why not user the AlarmManager and set a PendingIntent to fire off a broadcast? When you fire of the broadcast and catch it in your own BroadcastReciever that you've made, you'll have context in your BroadcastReciever with which to display your toast. Here's a quick high level example.
Where ever you're setting up your TimerTask in your activity, do this instead:
AlarmManager alarmManager = (AlarmManager)Context.getSystemService(Context.ALARM_SERVICE);
Intent broadcastIntent = new Intent("yourBroadcastAction");
PendingIntent pendingIntent = PendingIntenet.getBroadcast(this, 0, broadcastIntent, 0);
alarmManager.set(AlarmManager.ELAPSED_REALTIME, millisecondsUntilStop, broadcastIntent);
Then just create a BroadcastReciever that has a filter for the yourBroadcastAction and in the onRecieve() method do your toast like so:
public void onRecieve(Context context, Intent intent){
Toast.makeText(context,
getResources().getString(R.string.st_toast_msg_stopped),
Toast.LENGTH_LONG).show();
}