i'm trying to understand how android services works.
So i've created a simple application with an activity and a service, there is the code:
MainActivity.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Service"
android:id="@+id/buttonStart"
android:layout_marginTop="60dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:onClick="startButtonClickHandler"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Stop Service"
android:id="@+id/buttonStop"
android:layout_below="@+id/buttonStart"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:enabled="false"
android:onClick="stopButtonClickHandler" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/textView"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:text="Counter is: 0" />
</RelativeLayout>
MainActivity.java:
package com.example.wellsaid.provaservice;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.content.Intent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import org.w3c.dom.Text;
public class MainActivity extends Activity {
Button btn_stop = null;
Button btn_start = null;
/*---------------------------- CODICE NUOVO -----------------------------*/
private class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context arg0, Intent arg1) {
int datapassed = arg1.getIntExtra("count", 0);
TextView text = (TextView) findViewById(R.id.textView);
text.setText("Counter is: " + datapassed);
}
}
MyReceiver myreceiver = null;
/*---------------------------------------------------------------------*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_stop = (Button) findViewById(R.id.buttonStop);
btn_start = (Button) findViewById(R.id.buttonStart);
if(ExampleService.isRunning()){
btn_stop.setEnabled(true);
btn_start.setText("Send request");
Intent intent = new Intent(this, ExampleService.class);
intent.putExtra("count",0);
startService(intent);
}
/*--------------------- CODICE NUOVO -------------------------------*/
myreceiver = new MyReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ExampleService.RETURN_COUNTER);
registerReceiver(myreceiver, intentFilter);
/*------------------------------------------------------------------*/
}
public void startButtonClickHandler(View v){
if(!btn_stop.isEnabled()) {
btn_stop.setEnabled(true);
btn_start.setText("Send request");
}
Intent intent = new Intent(this, ExampleService.class);
intent.putExtra("count",0);
startService(intent);
}
public void stopButtonClickHandler(View v){
Intent intent = new Intent(this, ExampleService.class);
stopService(intent);
btn_start.setText("Start Service");
btn_stop.setEnabled(false);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
return super.onOptionsItemSelected(item);
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
unregisterReceiver(myreceiver);
super.onStop();
}
}
ExampleService.java
package com.example.wellsaid.provaservice;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.Log;
public class ExampleService extends Service {
/*--------------------- CODICE NUOVO-------------------------------*/
final static String RETURN_COUNTER = "RETURN_COUNTER";
/*----------------------------------------------------------------*/
@Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Intent intent = new Intent(this, ExampleService.class);
intent.putExtra("count",thread.getCounter());
startService(intent);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
ExampleThread thread = null;
private static boolean running = false;
public static boolean isRunning() { return running; }
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
running = true;
if(thread == null) {
int counter = intent.getExtras().getInt("count");
thread = new ExampleThread(counter);
thread.start();
}
else{
/*-----------------------CODICE NUOVO ----------------------*/
Intent send = new Intent();
send.setAction(RETURN_COUNTER);
send.putExtra("count",thread.getCounter());
sendBroadcast(send);
/*----------------------------------------------------------*/
}
return startId;
}
@Override
public void onDestroy() {
running = false;
thread.kill();
super.onDestroy();
}
private class ExampleThread extends Thread {
boolean stopped;
int counter = 0;
public ExampleThread(int counter){
this.counter = counter;
}
public void start(){
stopped = false;
super.start();
}
public int getCounter(){ return counter; }
public void kill(){
stopped = true;
}
public void run(){
while(!stopped) {
try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
counter++;
Log.i("Service", "Counter is: " + counter);
}
}
}
}
And that's my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.wellsaid.provaservice" >
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".ExampleService" />
</application>
</manifest>
I've tried to: 1) Open the application, launch the service with the start button, and stop it with the other. And all OK 2) Open the application, launch the service and close the application. And all OK (Service still running) 3) Open the application, launch the service, reopen the application and obtain the counter value. And all OK 4) Open the application, launch the service, close application, reopen application and stop the service. And all OK (also restart the service after close) The problem show up when i open, start service, close app, reopen to check counter number and then close again the application, after a while the service stop with no message in logcat :( On my android device in application administration i can see my application on a reboot state and after very long type it's restart and then stop again, on and on.... I've tested on a samsung galaxy express stock (android 4.1.2) And on a samsung galaxy tab 2 10.1 with cyanogenmod 10.1.3 (android 4.2.2)