barmi barmi - 4 months ago 14
Android Question

Android app in background

I have to create application and want to use it always when phone works, currently my code is:

Android Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.plan.pedometer">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:enabled="true"
android:name=".PedometerService"/>
<receiver
android:name=".receiver.StartPedometerServiceAtBootReceiver"
android:label="StartPedometerServiceAtBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>


StartPedometerServiceAtBootReceiver:

public class StartPedometerServiceAtBootReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Intent serviceIntent = new Intent(context, PedometerService.class);
context.startService(serviceIntent);
}
}
}


Service:

public class PedometerService extends IntentService {

private int Steps=0;

public PedometerService() {
super("Pedometer_Worker_Thread");
}

@Override
protected void onHandleIntent(Intent intent) {
putInSharedPreferences();
synchronized (this) {
try {
wait(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public void putInSharedPreferences(){
stepsNumbers = getApplicationContext().getSharedPreferences("stepsData", MODE_PRIVATE);
editorStepsNumbers=stepsNumbers.edit();
editorStepsNumbers.putInt(String.valueOf(STEPS),Steps).apply();
}

}


It works if I start
Service
in
MainActivity
by:

Intent intent = new Intent(getApplication(),PedometerService.class);
startService(intent);


and Service is running in background but when I restart my phone nothing happens and Service does not start.
I have one more question, this is
Pedometer
application, where should I put onSensorChange method in Service? Create something like while(1) in onHandleIntent() and put it there?

UPDATE - my actually code is:

I followed this tutorial https://github.com/codepath/android_guides/wiki/Starting-Background-Services
and tried to use
WakefulBroadcastReceiver

AndroidManifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.plan.pedomoter">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.plan.pedomoter.MyTestService"
android:exported="false"/>
<receiver android:name="com.plan.pedomoter.BootBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>


MainActivity:

public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onStart() {
super.onStart();
launchTestService();
}
public void launchTestService() {
// Construct our Intent specifying the Service
Intent i = new Intent(this, MyTestService.class);
// Add extras to the bundle
i.putExtra("foo", "bar");
// Start the service
startService(i);
}
}


Receiver:

public class BootBroadcastReceiver extends WakefulBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// Launch the specified service when this message is received
Intent startServiceIntent = new Intent(context, MyTestService.class);
startWakefulService(context, startServiceIntent);
}
}


Service:

public class MyTestService extends IntentService {
Handler handler;
// Must create a default constructor
public MyTestService() {
// Used to name the worker thread, important only for debugging.
super("test-service");
}
@Override
public void onCreate() {
super.onCreate(); // if you override onCreate(), make sure to call super().
// If a Context object is needed, call getApplicationContext() here.
handler = new Handler();
}
@Override
protected void onHandleIntent(Intent intent) {
WakefulBroadcastReceiver.completeWakefulIntent(intent);
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(MyTestService.this, "start", Toast.LENGTH_LONG).show();
int i = 0;
}
});
int i=0;
while(true){
i++;
// Do some work here
if(i>1000)
i=0;
}
}
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(MyTestService.this, "stop", Toast.LENGTH_SHORT).show();
}
}


I used while(true) in MyTestService for check that app is running in background, in project I will use sensors (this is pedometer application) then I want to put something like
MyAlarmReceiver
from tutorial to send data to the server several times a day.

Answer

try this Manifest.xml

    <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.mkonuk.rebootapplication">

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <service android:name=".MyService"/>

        <receiver android:name=".MyBootReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>


        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

MainActivity

    public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        startService(new Intent(getBaseContext(),MyService.class));
    }
}

MyService

 public class MyService extends Service {

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(getApplicationContext(),"Service started",Toast.LENGTH_LONG).show();
        return START_STICKY;
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(getApplicationContext(),"Service Destroyed",Toast.LENGTH_LONG).show();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

MyBootReceiver

    public class MyBootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent service  = new Intent(context,MyService.class);
        context.startService(service);
    }
}

I have tested when application started service will be start , even if your application destroyed service will be started again.Even if reboot android device service will be started.

Second question : if you will use sensor with service you need to register sensor listener and unregister sensor listener when service destroyed,oncreate method override sensor object and create sensor and sensor manager.In onstartCommand method register generated sensor listener sensor manager object ,unregister listener when service destroy you can check this link Accelemeter in android

if you want to send message from service to activity,you have to implement onbind() method ,activity need to bind on service check this link bind activity on service using sensor

bind/unbind service