Application skipping 600 frames - android

so im building this service for a application locker. it runs fine for the most part.but when i try to run the service to lock my own application(ie the app locker itself) there's a lag for like 4-5 seconds and then the lock activity launches. The logcat displays that it has skipped 600 frames and is doing too much work on the main thread. can anyone tell him how do i fix this or optimize this code
the AppActivities contains the name of activities that are to be ignored from launching the locker again when they are on top of the stack.eg the lockscreen activity to be shown to the user. The allowedapp is the last app verified by the user
public class LockerService extends Service {
String LockedApps[];
String allowedapp = null;
DataBaseHandler handler;
Intent pwdIntent = null;
ActivityManager am;
String[] AppActivities = { "com.packagename.Locker",
"com.packagename.Compare_Pattern",
"com.packagename.Captcha_Verfication",
"com.haibison.android.lockpattern.LockPatternActivity" };
private final static Handler servicehandler = new Handler() {
#Override
public void handleMessage(Message msg) {
}
};
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
handler = new DataBaseHandler(this);
am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
pwdIntent = new Intent(LockerService.this, Locker.class);
pwdIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
private Runnable checkforeground = new Runnable() {
public void run() {
handler.open();
LockedApps = handler.getPackages();
handler.close();
String packname = am.getRunningTasks(1).get(0).topActivity
.getPackageName();
String activityname = am.getRunningTasks(1).get(0).topActivity
.getClassName();
SharedPreferences sp = PreferenceManager
.getDefaultSharedPreferences(LockerService.this);
allowedapp = sp.getString("allowedapp", "anon");
// check if top application is mylocker application
if ((packname.equals("com.packagename"))
&& (allowedapp.equals("com.packagename"))) {
// do nothing
}
// check if top application is mylocker application and prevent relaunching the lockeractivity every 1.5 seconds
else if ((packname.equals("com.packagename"))
&& !(Arrays.asList(AppActivities).contains(activityname))) {
try {
Editor edit = sp.edit();
edit.putString("current_app", packname);
edit.commit();
startActivity(pwdIntent);
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else if ((Arrays.asList(LockedApps).contains(packname))
&& (allowedapp.equals(packname))) {
// do nothing
} else if ((Arrays.asList(LockedApps).contains(packname))) {
Editor edit = sp.edit();
edit.putString("current_app", packname);
edit.commit();
startActivity(pwdIntent);
}
servicehandler.postDelayed(this, 1500); // 1.5 seconds
}
};
#Override
public void onStart(Intent intent, int startId) {
servicehandler.removeCallbacks(checkforeground);
servicehandler.postDelayed(checkforeground, 1500);// 1.5 second
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
servicehandler.removeCallbacks(checkforeground);
stopSelf();
}
}

first of all as Gabe mentioned, a runnable runs on the main Thread.To solve the frames issue You'll need to create another new thread to run your code in the background.
Try this initialize executorService and LcThread and a boolean running_statusin your service.
The running_status variable is used to break the while loop of your thread so that stops looping in the back
#Override
public void onStart(Intent intent, int startId) {
running_status = true;
executorService = Executors.newSingleThreadExecutor();
servicehandler.removeCallbacks(LcThread);
LcThread = new LockerThread();
executorService.submit(LcThread);
}
create the following class
class LockerThread implements Runnable {
#Override
public void run() {
while(running_status){
//copy code from your old Runnable run method here
}
}
}
next modify the onDestroy method
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if (executorService != null) {
executorService.shutdown();
}
running_status = false;
servicehandler.removeCallbacks(LcThread);
stopSelf();
}
hope this solves your problem

A runnable still happens on the main thread. Services do not have their own thread by default, they run on the UI thread. If you want to do heavy processing in a service, you need to use a Thread or AsyncTask, so the processing does not occur on the UI thread.

Related

Viewpager swip delay

I'm using viewpager to show music and on swip left/right changing music according to that.When i swip viewpager it takes few sec in swip(it doesnot swip smoothly).
Code:
#Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
if (mCurrentPage > arg0) {
try {
Constant.position--;
musicService = new Intent(getApplicationContext(),
MusicService.class);
musicService.putExtra(Constant.NEXT, Constant.PREVIOUS);
startService(musicService);
musicService = null;
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
Constant.position++;
musicService = new Intent(getApplicationContext(),
MusicService.class);
musicService.putExtra(Constant.NEXT, Constant.NEXT);
startService(musicService);
musicService = null;
} catch (Exception e) {
e.printStackTrace();
}
}
mCurrentPage = arg0;
}
whenever I remove this code from onPageSelected, it swip smoothly. I had also putted this code inside handler but no befinits same issue.
Suggest me where I'm doing wrong and how to resolver this.
Update:
#Override
public int onStartCommand(final Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
mThread = new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
sPosition = Constant.position;
if (intent != null) {
try {
mPrevious = (String) intent.getExtras().get(
Constant.NEXT);
System.out.println("value of previous=" + mPrevious);
if (mPrevious.equalsIgnoreCase(Constant.PLAY)) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
cancelNotification();
} else {
mediaPlayer.start();
buildNotification(title, album);
}
} else if (mPrevious
.equalsIgnoreCase(Constant.PREVIOUS)) {
playPrevious();
} else if (mPrevious.equalsIgnoreCase(Constant.NEXT)) {
playNext();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
});
mThread.start();
return START_NOT_STICKY;
}
From the guide topic 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
Make sure your music service starts a thread to delegate work to.

Android, prevent to kill service/thread

how can i prevent this service with thread to dont be killed from android, i need this notifications always runnig, but when is mobile locked, nothing will happen. I think android kill service or thread or something like that
MainActivity in onCreate
startService(new Intent(this, NotifyService.class));
My service
public class NotifyService extends Service {
private DatabaseOp mDbHelper;
public Vibrator vibrator;
String username;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate ()
{
mDbHelper = new DatabaseOp(this);
final boolean cyklus = true;
Thread vlakno = new Thread (new Runnable()
{
#Override
public void run()
{
while (cyklus)
{
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String sysDate = getSysDate();
String sysDate2 = getSysDate2();
String time = getSysTime();
mDbHelper.open();
Log.v( "sysDate", sysDate );
Cursor cursorU = mDbHelper.fetchUlohaS(0, sysDate);
if (cursorU.getCount() > 0)
{
String idU = cursorU.getString(cursorU.getColumnIndexOrThrow(DatabaseOp.KEY_ID));
String dbDateU = cursorU.getString(cursorU.getColumnIndexOrThrow(DatabaseOp.KEY_DATE));
String menoU = cursorU.getString(cursorU.getColumnIndexOrThrow(DatabaseOp.KEY_NAZOV));
String mHodina = getResources().getString(R.string.cas)+" "+cursorU.getString(cursorU.getColumnIndexOrThrow(DatabaseOp.KEY_HODINA));
Log.v( "task", dbDateU+"/"+sysDate );
if (dbDateU.equals(sysDate))
{
Notify(menoU, mHodina, idU, 0);
}
}
Cursor cursorS = mDbHelper.fetchSviatokS(3, sysDate2);
if (cursorS.getCount() > 0)
{
String idS = cursorS.getString(cursorS.getColumnIndexOrThrow(DatabaseOp.KEY_ID));
String dbDateS = cursorS.getString(cursorS.getColumnIndexOrThrow(DatabaseOp.KEY_DATUM));
String menoS = cursorS.getString(cursorS.getColumnIndexOrThrow(DatabaseOp.KEY_NAZOV));
if (dbDateS.equals(sysDate2) && time.equals("09:00"))
{
Notify(menoS,getResources().getString(R.string.title_section4), idS, 3);
}
}
mDbHelper.close();
}
}
});
vlakno.start();
}
}
Have you tried to use ForgroundService?
Checkout this repo for an example - https://github.com/supercurio/foreground-service-sample-app
I think you should consider AlarmManager. See http://developer.android.com/reference/android/app/AlarmManager.html.
To tip the system to keep your Service alive as long as possible (i.e. before RAM is very short or user kills the service by hand through application info screen), you need to run it as a foreground service -- by using startForeground() method.
If you're looking for a way to run when the device is turned off, read the Keeping The Device Awake training page and consider using AlarmManager instead as suggested by #khris if your task is not very critical in terms of timing precision.

Android Handler calling Runnable twice

I know this question has been asked before, but there was no answer provided. I also tried looking elsewhere, have traced the function calls and checked everything, but I cannot figure out the answer.
I have a very simple Handler, which calls a Runnable variable every second. It is meant to keep a track of time spent on the activity.
So the handler begins a call in onCreate, and in the Runnable there is a postDelayed(runnableVar, 1000) to continue running it every second. This is updating a text view in the activity.
The text view is showing everything in doubles. I checked my log and found that the runnable is called twice. I don't know why this is happening. Here is my code:
//My runnable variable in the activity
private Runnable mUpdateTimeTask = new Runnable(){
#Override
public void run(){
if (gameTimer != null) {
Log.d("UPDATERUNNABLE", "Inside runnable run");
gameTimer.setText(getTime());
}
mHandler.postDelayed(this,1000);
}
};
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Log.d(TRIALTAG,"Inside on create");
startMins = mPrefsMin; //This is set in onPause and retrieved onResume
startSecs = mPrefsSecs;
Log.d(TRIALTAG,"Start mins : " + startMins + " Start Secs : " + startSecs);
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.post(mUpdateTimeTask);
}
private String getTime() {
String finalTime;
Log.d("GETTIME", "Start secs is : " + startSecs);
if(startSecs >= 60){
startSecs=0;
startMins++;
}
if(startSecs<10){
finalTime = startMins+":0"+startSecs;
}else{
finalTime = startMins+":"+startSecs;
}
startSecs++;
return finalTime;
}
#Override
protected void onPause(){
super.onPause();
Log.d(TRIALTAG,"On Pause CALLED");
mHandler.removeCallbacks(mUpdateTimeTask);
SharedPreferences.Editor ed = mPrefs.edit();
ed.putInt("my_mins", startMins);
ed.putInt("my_secs", startSecs);
ed.commit();
}
#Override
protected void onResume(){
super.onResume();
Log.d(TRIALTAG,"On RESUME CALLED");
if(gameTimer != null){
mPrefs = getSharedPreferences("mPrefs", MODE_PRIVATE);
mPrefsMin = mPrefs.getInt("my_mins", 0);
mPrefsSecs = mPrefs.getInt("my_secs", 0);
mHandler.post(mUpdateTimeTask);
}else{
mPrefsMin = 0;
mPrefsSecs = 0;
}
}
All this is within my activity class. What am I doing wrong??
The problem is that you are posting your Runnable object twice - in onCreate and onResume methods. Try modifying your onResume method and removing the previous added Runnable
#Override
protected void onResume(){
super.onResume();
Log.d(TRIALTAG,"On RESUME CALLED");
if(gameTimer != null){
mPrefs = getSharedPreferences("mPrefs", MODE_PRIVATE);
mPrefsMin = mPrefs.getInt("my_mins", 0);
mPrefsSecs = mPrefs.getInt("my_secs", 0);
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.post(mUpdateTimeTask);
}else{
mPrefsMin = 0;
mPrefsSecs = 0;
}
}
There is an another way also that you can use to update the UI on specific time interval.
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (true) {
try {
Thread.sleep(10000);
mHandler.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
gameTimer.setText(getTime());
}
});
} catch (Exception e) {
// TODO: handle exception
}
}
}
}).start();
in onCreate remove
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.post(mUpdateTimeTask);

Keep Service running

Can anyone tell me the way to keep a Service always running or restarting itself when the user close it? I've watched that facebook services restart when i clear memory.
I don't want to make ForegroundServices.
You should create a sticky service. Read more about it here.
You can do this by returning START_STICKY in onStartCommand.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
Read also about application:persistent which is "Whether or not the application should remain running at all times". This is more troublesome - System will try not to kill your app which will effect others in the system, you should be careful using it.
I copied this from a service I used in an app I did before.
ITS IMPORTANT TO NOT UPDATE ANY UI. because you have no user interface in services. this applies to Toasts as well.
good luck
public class nasserservice extends Service {
private static long UPDATE_INTERVAL = 1*5*1000; //default
private static Timer timer = new Timer();
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
super.onCreate();
_startService();
}
private void _startService()
{
timer.scheduleAtFixedRate(
new TimerTask() {
public void run() {
doServiceWork();
}
}, 1000,UPDATE_INTERVAL);
Log.i(getClass().getSimpleName(), "FileScannerService Timer started....");
}
private void doServiceWork()
{
//do something wotever you want
//like reading file or getting data from network
try {
}
catch (Exception e) {
}
}
private void _shutdownService()
{
if (timer != null) timer.cancel();
Log.i(getClass().getSimpleName(), "Timer stopped...");
}
#Override
public void onDestroy()
{
super.onDestroy();
_shutdownService();
// if (MAIN_ACTIVITY != null) Log.d(getClass().getSimpleName(), "FileScannerService stopped");
}
}

How to implement handlers in Android from a thread in seperate file

I was wondering how to use a handler in android to send two messages from a separate thread to update UI. The thread is declared in another file. I understand that using java Thread is not desirable in Android, but I have given up using android methods, they are terrible. The handler messages are sent every 200 miliseconds from my declared thread. I cannot find a decent example of how to implement it.
Here is my extended thread. This is called from the activity.
import java.io.IOException;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Message;
public class MPlayer extends Thread {
private volatile boolean playing = false;
private volatile boolean finished = false;
MediaPlayer player;
Message msg;
Bundle bundle;
String filepath;
/* other fields, constructor etc. */
public MPlayer(String path) {
filepath = path;
player = new MediaPlayer();
bundle = new Bundle();
msg = new Message();
start();
}
public void seekMPlayer(int i) {
// TODO Auto-generated method stub
player.seekTo(i);
}
public boolean getPlaying() {
// TODO Auto-generated method stub
return playing;
}
#Override
public void run() {
try {
player.setDataSource(filepath);
player.prepare();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (!finished) {
while (playing && !finished) {
try {
Thread.sleep(200);
if (playing && !finished) {
bundle.putString("progval", songTime());
// msg.setData(bundle);
// threadHandler.sendMessage(msg);
} else
break;
} catch (InterruptedException e) {
}
}
}
}
public synchronized void pauseMPlayer() {
playing = false;
player.pause();
}
public synchronized void PlayMPlayer() {
playing = true;
player.start();
// call notify() here when you switch to wait/notify.
}
public void stopMPlayer() {
playing = false;
finished = true;
player.release();
// call notify() here too.
}
private String songTime() {
// TODO Auto-generated method stub
if (filepath != null) {
int progressseconds = (int) ((player.getCurrentPosition() / 1000) % 60);
int progressminutes = (int) ((player.getCurrentPosition() / 1000) / 60);
int durationseconds = (int) ((player.getDuration() / 1000) % 60);
int durationminutes = (int) ((player.getDuration() / 1000) / 60);
String progmin, progsec, durmin, dursec;
if (progressminutes >= 10)
progmin = Integer.toString(progressminutes);
else
progmin = "0" + Integer.toString(progressminutes);
if (progressseconds >= 10)
progsec = Integer.toString(progressseconds);
else
progsec = "0" + Integer.toString(progressseconds);
if (durationminutes >= 10)
durmin = Integer.toString(durationminutes);
else
durmin = "0" + Integer.toString(durationminutes);
if (durationseconds >= 10)
dursec = Integer.toString(durationseconds);
else
dursec = "0" + Integer.toString(durationseconds);
return (progmin + ":" + progsec + "/" + durmin + ":" + dursec);
} else {
return ("No File!");
}
}
}
Handler should bind a Looper of the thread. Use this constructor to specify a thread looper
Handler handler = new Handler(Looper.getMainLooper());
And now the you can send message to the main thread
There is nothing wrong in using Java threads in Android but it is a bit overkill to use it just for sending periodic messages. The recommended way to do it is to use Handler.postDelayed. This article suggests following method: put all your updating code into a Runnable and add postDelayed call to the end of this Runnable's run() to schedule it again. This approach eliminates overhead of having a background thread.
However it is easy to use Handler to send messages from the other thread. As I understand you are trying to send messages to some UI component so it can update itself.
In my application I faced a similar problem. I declared a handler inside the UI component and passed this handler to a background thread in a constructor parameter.
The UI part looks like:
class MyActivity extends Activity {
Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
// update UI according to a content of msg from background thread
// ...
}
};
private Thread mBackgroundWorker = new BackgroundThread(mHandler);
protected void onCreate(Bundle savedInstanceState) {
// ...
mBackgroundWorker.start();
// ...
}
protected void onDestroy() {
// we created the thread in this activity
// so we should manage its lifecycle here
mBackgroundWorker.interrupt();
}
}
And the background thread is implemented like
class BackgroundThread extends Thread {
private final mHandler;
public BackgroundThread(Handler h) {
mHandler = h;
}
public void run() {
// do some processing...
mHandler.sendMessage(/*some message to update an UI*/);
// ...
}
}

Categories

Resources