stopService(Intent) Method Not Stopping The Service - android

I called the stopService() method from the calling class when the calling activity exits, and the service does not stop. It keeps on running in the background and can thus be a hastle to the end user. Any help would be greatly appreciated..
Code:
public class MainActivity2 extends ActionBarActivity {
ListView listView;
static int cnt1=0;
static int bob=1;
RelativeLayout background2;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_activity2);
background2 = (RelativeLayout) findViewById(R.id.background);
int num = 0;
final ListView theListView = (ListView) findViewById(R.id.listView);
Intent calledActivity = getIntent();
final List pe = calledActivity.getExtras().getStringArrayList("Caller1");
String[] s = new String[pe.size()];
for (int i = 0; i < pe.size(); i++) {
s[i] = (String) pe.get(i);
}
final ListAdapter theAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, pe);
theListView.setAdapter(theAdapter);
final int cnt = 1;
Intent mIntent = new Intent(this, MyService.class);
mIntent.putStringArrayListExtra("Caller2", (ArrayList<String>) pe);
mIntent.putExtra("intCall",bob);
startService( mIntent);
theListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String s1 = String.valueOf(parent.getItemAtPosition(position));
pe.remove(s1);
if (pe.size() == 0) {
stopService(new Intent(MainActivity2.this, MyService.class));
Intent goback;
goback = new Intent(MainActivity2.this, MainActivity.class);
startActivity(goback);
}
((BaseAdapter) theAdapter).notifyDataSetChanged();
}
});
}
MY SERVICE CLASS:
public class MyService extends Service {
public MyService() {
}
#Override
public IBinder onBind(Intent arg0) {
return null;}
#Override
public void onCreate() {
Toast.makeText(this, "Congrats! Blocker Created", Toast.LENGTH_LONG).show();
}
#Override
public void onStart(final Intent intent, int startId) {
int i=0;
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(1);
ActivityManager.RunningTaskInfo ar = tasks.get(0);
String activityOnTop=ar.topActivity.getClassName();
Intent lockIntent = new Intent(MyService.this, LockScreen.class);
lockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ComponentName componentInfo = tasks.get(0).topActivity;
if(!componentInfo.getPackageName().equals("com.example.epiclapser.noprocrastinate"))
{
startActivity(lockIntent);
Log.v("iwashere", "-- ACTIVITY --");
}
}
},
0,
1000);
Toast.makeText(this, "My Blocker Started", Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
Toast.makeText(this, "MyService Stopped", Toast.LENGTH_LONG).show();
super.onDestroy();
}
}

Docs say:
Each timer has one thread on which tasks are executed sequentially.
So I see you have a thread in your service.If you created a thread,you can not stop it until it does it's task,unless it has a task that involves a loop.In this situation,in loop condition,you can check if this thread received stop message(cancel) or not?And if is received,stop the loop.

Note to self:
Bro, put System.exit(0) in onDestroy() , after timer.cancel() & timer.purge()

Related

how to pass a string data to my activity from a service

I have an activity that runs a timer and I want to broadcast that timer and set a receiver to my activity and display the timer. I know that it can be done using a broadcast and receiving that broadcast intent but I don't know how to do it.
here are my codes
public class MyService extends Service {
private Vibrator v;
NotificationCompat.Builder notification;
private static final int uniqueID = 71399;
#Override
public void onCreate() {
super.onCreate();
notification = new NotificationCompat.Builder(this);
notification.setAutoCancel(true);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
SharedPreferences sharedPreferences = getSharedPreferences("Timer", Context.MODE_PRIVATE);
int dur = sharedPreferences.getInt("duration", 0);
//background timer
CountDownTimer countDownTimer = new CountDownTimer(dur, 1000) {
#Override
public void onTick(long dur) {
long millis= dur;
String hms= String.format("%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))
//seconds
,TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);
startnotif(hms);
startBroadcast(hms);
}
#Override
public void onFinish() {
long n[] = {1,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000};
v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(n, -1);
endnotif();
onDestroy();
}
};
countDownTimer.start();
return START_STICKY;
}
public void onDestroy() {
stopSelf();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
//notification
public void startnotif(String hms)
{
String noT = hms;
notification.setSmallIcon(R.mipmap.ic_launcher);
notification.setTicker("apps are blocked!");
notification.setWhen(System.currentTimeMillis());
notification.setContentTitle("Be productive!");
notification.setContentText(hms);
ClickNotif();
}
public void endnotif(){
notification.setContentText("00:00");
notification.setTicker("apps are now unblocked!");
notification.setWhen(System.currentTimeMillis());
notification.setContentTitle("You survived!");
notification.setContentText("Apps are now unblocked!");
ClickNotif();
}
//other parts of notif
public void ClickNotif(){
Intent intent1 = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
notification.setContentIntent(pendingIntent);
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nm.notify(uniqueID, notification.build());
}
The Target activity
public class Main2Activity extends AppCompatActivity {
private Button btntest;
private TextView timer;
private Spinner spinner, spinner2;
public int hours, mins, duration;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
btntest = (Button) findViewById(R.id.startbtn);
timer = (TextView) findViewById(R.id.Timertxt);
//setting up 2 spinners
spinner = (Spinner) findViewById(R.id.hrspinner);
String [] values = {"00","01","02","03","04","05","06"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, values);
adapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
spinner.setAdapter(adapter);
spinner2 = (Spinner) findViewById(R.id.minspinner);
String [] values2 = {"00","01","10","20","30","40","50","60"};
ArrayAdapter<String> adapter2 = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, values2);
adapter2.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
spinner2.setAdapter(adapter2);
//button start
btntest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String spin=spinner.getSelectedItem().toString();
hours = Integer.parseInt(spin);
hours = hours*3600000;
String spin2=spinner2.getSelectedItem().toString();
mins = Integer.parseInt(spin2);
mins = mins*60000;
duration = hours+mins;
setParam(duration);
startService(duration);
}
});
}
/*timer part
public void setParam(int param){
CountDownTimer countDownTimer = new CountDownTimer(param, 1000) {
#Override
public void onTick(long param) {
long millis= param;
String hms= String.format("%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))
//seconds
,TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);
timer.setText(hms);
}
#Override
public void onFinish() {
timer.setText("00:00");
}
};
countDownTimer.start();
}*/
//saving data and passing intent to service
public void startService(int duration)
{
int d = duration;
SharedPreferences sharedPreferences = getSharedPreferences("Timer", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("duration", d);
editor.apply();
Intent intent = new Intent(this,MyService.class);
startService(intent);
}
}
how can I show that timer to my text field? Please help!
you can use LocalBroadcastManager like this :
in your service
private LocalBroadcastManager broadcaster;
#Override
public void onCreate() {
broadcaster = LocalBroadcastManager.getInstance(this);
}
private void sendData(){
Intent intent = new Intent("MyData");
broadcaster.sendBroadcast(intent);
}
and call sendData() wherever you want, and in your activity write
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
/*
this called when app receive notification and MainActivity is opened
* see FcmMessagingService.class to see where it called
*/
#Override
public void onReceive(Context context, Intent intent) {
// Log.d("broadcaster", "onReceive BaseActivity");
// write whatever you want and you cant use intent.getString("key");
}
};
#Override
protected void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver((mMessageReceiver), new IntentFilter("MyData"));
}

How to set limit when user enter wrong pattern many time?

Currentlly I am implementing pattern lock application and I want to set limit when user enter wrong pattern many time.Example,If user enter wrong pattern at that time set limit(3 or 4 time limit) and set delay 30 second and after 30 second give permission to enter pattern.
So,If anyone know how i can do this please give idea of that.
Here this my Reciever
public class LockScreenReceiver extends DeviceAdminReceiver {
Context context;
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i("Action...","..."+action);
//If the screen was just turned on or it just booted up, start your Lock Activity
if(action.equals(Intent.ACTION_SCREEN_OFF) || action.equals(Intent.ACTION_BOOT_COMPLETED))
{
Intent i = new Intent(context, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
#Override
public void onPasswordFailed(Context ctxt, Intent intent) {
DevicePolicyManager mgr = (DevicePolicyManager) ctxt.getSystemService(Context.DEVICE_POLICY_SERVICE);
int no = mgr.getCurrentFailedPasswordAttempts();
if (no >= 3) {
context.startActivity(new Intent(context,ChangeActivity.class));
}
}
}
Service
public class LockScreenService extends Service {
DeviceAdminReceiver receiver;
#Override
public IBinder onBind(Intent intent) {
return null;
}
// Register for Lockscreen event intents
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
receiver = new LockScreenReceiver();
registerReceiver(receiver, filter);
startForeground();
return START_STICKY;
}
// Run service in foreground so it is less likely to be killed by system
private void startForeground() {
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(getResources().getString(R.string.app_name))
.setTicker(getResources().getString(R.string.app_name))
.setContentText("Running")
.setContentIntent(null)
.setOngoing(true)
.build();
startForeground(9999,notification);
}
#Override
#SuppressWarnings("deprecation")
public void onCreate() {
KeyguardManager.KeyguardLock key;
KeyguardManager km = (KeyguardManager)getSystemService(KEYGUARD_SERVICE);
//This is deprecated, but it is a simple way to disable the lockscreen in code
key = km.newKeyguardLock("IN");
key.disableKeyguard();
//Start listening for the Screen On, Screen Off, and Boot completed actions
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
//Set up a receiver to listen for the Intents in this Service
receiver = new LockScreenReceiver();
registerReceiver(receiver, filter);
super.onCreate();
}
#Override
public void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
}
Activity
public class MainActivity extends ActionBarActivity {
private Lock9View lock9View;
private static String MY_PREFS_NAME = "PatternLock";
private static String PATTERN_KEY;
SharedPreferences prefs;
Button btnChange;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startService(new Intent(MainActivity.this, LockScreenService.class));
makeFullScreen();
setContentView(R.layout.activity_main);
btnChange = (Button)findViewById(R.id.btnChange);
btnChange.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent in = new Intent(MainActivity.this,ChangeActivity.class);
startActivity(in);
}
});
prefs = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);
lock9View = (Lock9View) findViewById(R.id.lock_9_view);
lock9View.setCallBack(new Lock9View.CallBack() {
#Override
public void onFinish(String password) {
PATTERN_KEY = prefs.getString("Pattern", "invalid");
if (PATTERN_KEY.equals("invalid")) {
Toast.makeText(MainActivity.this, "Options --> Create new Pattern", Toast.LENGTH_LONG).show();
} else {
if (password.equals(PATTERN_KEY)) {
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
}else{
Context context = getApplicationContext();
// Create layout inflator object to inflate toast.xml file
LayoutInflater inflater = getLayoutInflater();
// Call toast.xml file for toast layout
View toastRoot = inflater.inflate(R.layout.layout_toast3, null);
Toast toast = new Toast(context);
// Set layout to toast
toast.setView(toastRoot);
toast.setGravity(Gravity.HORIZONTAL_GRAVITY_MASK | Gravity.BOTTOM,
0, 0);
toast.setDuration(Toast.LENGTH_LONG);
toast.show();
}
}
}
});
}
private void makeFullScreen() {
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
if(Build.VERSION.SDK_INT < 19) { //View.SYSTEM_UI_FLAG_IMMERSIVE is only on API 19+
this.getWindow().getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
} else {
this.getWindow().getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE);
}
}
#Override
public void onBackPressed() {
return; //Do nothing!
}
public void unlockScreen(View view) {
//Instead of using finish(), this totally destroys the process
android.os.Process.killProcess(android.os.Process.myPid());
}
}
So,How i can achieve this...
Have a int field like failedCounter and increment it each time user inputs invalid patterns check if reached the limit then disable the input interface and have a handler to reset the value after the time delay.
int failedCount = 0;
final static int LIMIT = 5; //set your limit here
private void invalidPattern() {
if (++failedCount == LIMIT) {
//disable the input
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//reset the failed count
faildCount = 0;
//Enable the input interface here
}
}, 30000); // 30Sec delay
}
}
Use this two methods -
ScheduledThreadPoolExecutor c1;
private void IncorrectCallCounter() {
if (failedCounter>=0)
{
c1.shutdownNow();
LockScreenFor30Second();
}else
{
if (c1!=null)
c1.shutdownNow();
}
c1 = new ScheduledThreadPoolExecutor(1);
c1.schedule(new Runnable() {
#Override
public void run() {
failedCounter=0;
c1.shutdownNow();
}
}, 15, TimeUnit.SECONDS);
}
ScheduledThreadPoolExecutor c2;
private void LockScreenFor30Second() {
//Lock Screen Here
c2 = new ScheduledThreadPoolExecutor(1);
c2.schedule(new Runnable() {
#Override
public void run() {
//Unlock Screen Here
c2.shutdownNow();
}
}, 30, TimeUnit.SECONDS);
}
Declare failedCounter globally
private int failedCounter=0;
And call this method when you detect wrong pattern -
failedCounter=failedCounter+1;
IncorrectCallCounter();
If user enter wrong pattern 4 times in 15 seconds then this will call LockScreenFor30Second method. and inside LockScreenFor30Second add your code.

How to know if phone app is closed

please explain me how does android call lock screen after closing emergency dialer. I've tried to check every second if emergency call is the top activity if it's not then i just lock device but this didn't do it's job in android 5.0 and higher. So, I need another solution.
My code:
private static final long INTERVAL = TimeUnit.SECONDS.toMillis(1/100);
private Thread t = null;
private Context ctx = null;
private boolean running = false;
public MyService2() {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
running = true;
ctx = this;
Log.i("Point","PreRun");
t = new Thread(new Runnable() {
#Override
public void run() {
Log.i("Point","preloop");
do {
Log.i("Point", "Prechech");
if (activityManager.getRunningTasks(1).get(0).topActivity.getPackageName().equals("com.android.phone") || activityManager.getRunningTasks(1).get(0).topActivity.getPackageName().equals("com.android.dialer"))
{
try {
Thread.sleep(INTERVAL);
} catch (InterruptedException e) {
Log.i("Point", "Thread interrupted: 'KioskService'");
}
} else {
running=false;
Log.i("Task is",activityManager.getRunningTasks(1).get(0).topActivity.getPackageName());
stopSelf();
}
}while (running) ;
}
});
t.start();
Log.i("Point","Done");
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i("Point","Service is stopped");
}
}
And this:
public class MyActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent("com.android.phone.EmergencyDialer.DIAL");
startActivity(intent);
Intent intent1 = new Intent(MyActivity.this,MyService2.class);
startService(intent1);
}
});
}
}
You can launch your emergency dialer like this:
Intent intent = new Intent("android.intent.action.MAIN");
intent.setComponent(ComponentName.unflattenFromString("com.android.phone/.EmergencyDialer"));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Moreover please check if you have declared your service properly in manifest.
<service
android:name=".MyService2">
</service>

Service stops when activity is destroyed

I have searched a lot on stackoverflow regarding this issue but nothing seems to work.
I am developing a music player which plays music by binding to a service. I have two activities.The first activity(called as AllSongs) provides me with the list of songs.When I select a song it starts another activity(called as SongUI) which plays the song by binding to a service.
Now when I move back to my AllSongs activity the music stops.Now when I select a song again,my SongUI activity is started and when I go back to my AllSongs activity, the music does not stop and plays in the background.I am not able to understand what is causing this issue. I think I am doing something silly somewhere but am not able to figure it out. I want songs to be played in the background same as any music player does.Here is the code.
AllSongs activity:
public class AllSongs extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.allsongs_activity);
getSongList();
from = new String[]{MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.DURATION};
to = new int[]{R.id.title_entry,R.id.artist_entry,R.id.duration_entry};
listView = (ListView) findViewById(R.id.listView);
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,R.layout.singlesong,myCursor,from,to,SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent songUIIntent = new Intent(getApplicationContext(),SongUI.class);
songUIIntent.putExtra("position",id);
startActivity(songUIIntent);
}
});
}
private void getSongList() {
ContentResolver myContentResolver = getContentResolver();
myCursor = myContentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,null,null,null,null);
if(myCursor!=null && myCursor.moveToFirst()) {
int titleColumn = myCursor.getColumnIndex(MediaStore.Audio.Media.TITLE);
int idColumn = myCursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID);
int artistColumn = myCursor.getColumnIndex(android.provider.MediaStore.Audio.Media.ARTIST);
long albumID = myCursor.getLong(myCursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
do {
long ID = myCursor.getLong(idColumn);
String title = myCursor.getString(titleColumn);
String artist = myCursor.getString(artistColumn);
songList.add(new currentSong(ID,title,artist));
}while (myCursor.moveToNext());
}
}
#Override
protected void onDestroy() {
super.onDestroy();
}
}
SongUI activity:
public class SongUI extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.song_ui);
button = (Button) findViewById(R.id.play);
isBound = false;
Intent receivedIntent = getIntent();
position = receivedIntent.getLongExtra("position",0);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main,menu);
return super.onCreateOptionsMenu(menu);
}
public void playAudio(View view) {
Intent objIntent = new Intent(this,MyService.class);
if(!isBound)
{
objIntent.putExtra("position", position);
startService(objIntent);
isBound=true;
button.setBackgroundResource(R.drawable.play);
bindService(objIntent, myConnection, Context.BIND_AUTO_CREATE);
}
else
{
myServiceObject.pauseAudio();
button.setBackgroundResource(R.drawable.play);
isBound=false;
unbindService(myConnection);
}
}
public void stopAudio(View view) {
Intent objIntent = new Intent(this,MyService.class);
if(isBound)
{
isBound=false;
unbindService(myConnection);
stopService(objIntent);
}
else {
stopService(objIntent);
}
button.setBackgroundResource(R.drawable.play);
}
private ServiceConnection myConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
myServiceObject = ((MusicBinder) service).getService();
isBound = true;
}
public void onServiceDisconnected(ComponentName arg0) {
isBound = false;
}
};
#Override
protected void onDestroy() {
super.onDestroy();
if (isBound) {
unbindService(myConnection);
isBound = false;
}
}
}
MyService class
public class MyService extends Service {
#Override
public void onCreate() {
super.onCreate();
player = new MediaPlayer();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "on startCommand is called");
long id = intent.getLongExtra("position",0);
Uri contentUri = ContentUris.withAppendedId(
android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
Log.d(TAG, "Service is Started");
player = MediaPlayer.create(this,contentUri);
player.start();
Intent notIntent = new Intent(this, SongUI.class);
notIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendInt = PendingIntent.getActivity(this, 0,
notIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder builder = new Notification.Builder(this);
builder.setContentIntent(pendInt)
.setSmallIcon(R.drawable.play)
.setTicker(songTitle)
.setOngoing(true)
.setContentTitle("Playing")
.setContentText(songTitle);
Notification notification = builder.build();
startForeground(NOTIFY_ID, notification);
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "on Bind is called");
return myBinder;
}
#Override
public boolean onUnbind(Intent intent){
Log.d(TAG,"onUnbind is called");
player.stop();
player.release();
return false;
}
public class MusicBinder extends Binder {
MyService getService() {
return MyService.this;
}
}
public void pauseAudio() {
if(player.isPlaying()) {
player.pause();
}
}
#Override
public void onDestroy() {
Log.d(TAG,"on destroy is called");
stopForeground(true);
}
I have figured out where I was going wrong. I was calling unbindService(myConnection) in onDestroy of my SongsUI activity which was stopping the playback.
And the reason why this was not the case the second time round was that I was returning false in onUnbind method. So the system was not calling onBind method the second time and subsequently onUnbind was also not getting called. Hence the playback was also not stopping.

Stopping a thread inside a service

I have a thread inside a service and I would like to be able to stop the thread when I press the buttonStop on my main activity class.
In my main activity class I have:
public class MainActivity extends Activity implements OnClickListener {
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
buttonStart = (Button) findViewById(R.id.buttonStart);
buttonStop = (Button) findViewById(R.id.buttonStop);
buttonStart.setOnClickListener(this);
buttonStop.setOnClickListener(this);
}
public void onClick(View src) {
switch (src.getId()) {
case R.id.buttonStart:
startService(new Intent(this, MyService.class));
break;
case R.id.buttonStop:
stopService(new Intent(this, MyService.class));
break;
}
}
}
And in my service class I have:
public class MyService extends Service {
...
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
int icon = R.drawable.myicon;
CharSequence tickerText = "Hello";
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, "notification title", "notification message", pendingIntent);
startForeground(ONGOING_NOTIFICATION, notification);
...
}
#Override
public void onStart(Intent intent, int startid) {
Thread mythread= new Thread() {
#Override
public void run() {
while(true) {
MY CODE TO RUN;
}
}
}
};
mythread.start();
}
}
what is the best way to stop the mythread?
Also is the way that I have stopped the service by stopService(new Intent(this, MyService.class)); correct?
You can't stop a thread that has a running unstoppable loop like this
while(true)
{
}
To stop that thread, declare a boolean variable and use it in while-loop condition.
public class MyService extends Service {
...
private Thread mythread;
private boolean running;
#Override
public void onDestroy()
{
running = false;
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startid) {
running = true;
mythread = new Thread() {
#Override
public void run() {
while(running) {
MY CODE TO RUN;
}
}
};
};
mythread.start();
}
You call onDestroy() method for stop service.

Categories

Resources