Intent Service如何在后台持续运行?

时间:2016-02-16 13:09:34

标签: android broadcastreceiver intentservice activity-recognition

所以我使用的是Activity Recognition API,我为被叫ActivityRecognitionIntentService创建了一个服务。

我真的希望这一直在后台工作。

问题是应用程序在缓存的正在运行的服务中显示但在我退出应用程序时关闭并且不在后台运行。

我在主要活动中使用广播接收器来更新UI。

我使用IntentService,我创建了onStartCommand,返回START_STICKY

import android.app.IntentService;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.ActivityRecognition;
import com.google.android.gms.location.ActivityRecognitionResult;
import com.google.android.gms.location.DetectedActivity;

public class ActivityRecognitionIntentService extends IntentService implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

    Context mContext;
    GoogleApiClient mGApiClient;
    BroadcastReceiver receiver;
    private static final String TAG = ActivityRecognitionIntentService.class.getSimpleName();

    public ActivityRecognitionIntentService() {
        super("ActivityRecognitionIntentService");

    }

    @Override
    protected void onHandleIntent(Intent intent) {
        if(ActivityRecognitionResult.hasResult(intent)) {
            //Extract the result from the Response
            ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
            DetectedActivity detectedActivity = result.getMostProbableActivity();

            //Get the Confidence and Name of Activity
            int confidence = detectedActivity.getConfidence();
            String mostProbableName = getActivityName(detectedActivity.getType());

            //Fire the intent with activity name & confidence
            Intent i = new Intent("ImActive");
            i.putExtra("activity", mostProbableName);
            i.putExtra("confidence", confidence);

            Log.d(TAG, "Most Probable Name : " + mostProbableName);
            Log.d(TAG, "Confidence : " + confidence);

            //Send Broadcast to be listen in MainActivity
            this.sendBroadcast(i);

        }else {
            Log.d(TAG, "Intent had no data returned");
        }
    }

    //Get the activity name
    private String getActivityName(int type) {
        switch (type)
        {
            case DetectedActivity.IN_VEHICLE:
                return "still";
            case DetectedActivity.ON_BICYCLE:
                return "moving";
            case DetectedActivity.ON_FOOT:
                return "moving";
            case DetectedActivity.WALKING:
                return "moving";
            case DetectedActivity.STILL:
                return "still";
            case DetectedActivity.TILTING:
                return "still";
            case DetectedActivity.UNKNOWN:
                return "still";
            case DetectedActivity.RUNNING:
                return "moving";

        }
        return "N/A";
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent,flags,startId);
        buildGoogleClient();
        Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
        return START_STICKY;
    }

    private boolean isPlayServiceAvailable() {
        return GooglePlayServicesUtil.isGooglePlayServicesAvailable(mContext) == ConnectionResult.SUCCESS;
    }

    private void buildGoogleClient()
    {
        //Check Google Play Service Available
        if (isPlayServiceAvailable()) {
            mGApiClient = new GoogleApiClient.Builder(this)
                    .addApi(ActivityRecognition.API)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build();
            //Connect to Google API
            mGApiClient.connect();
        }
    }

    @Override
    public void onConnected(Bundle bundle) {
        Intent i = new Intent(this, ActivityRecognitionIntentService.class);
        PendingIntent mActivityRecongPendingIntent = PendingIntent
                .getService(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);

        Log.d(TAG, "connected to ActivityRecognition");
        ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(mGApiClient, 0, mActivityRecongPendingIntent);

    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.d(TAG, "Suspended to ActivityRecognition");
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.d(TAG, "Not connected to ActivityRecognition");
    }

}

我还在清单

中声明了服务
 <service android:name=".ActivityRecognitionIntentService"
        android:exported="false"/>

连同必要的权限

<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

1 个答案:

答案 0 :(得分:0)

您需要扩展服务而不是IntentService,并且您必须显示正在进行的通知,以便操作系统不会终止您的服务

这是一个例子:

public class RunnerService extends Service {

    private Notification mNotification;
    private static int notificationId = 1;


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

    @Override
    public void onCreate() {
        super.onCreate();

        // get abitmap to be displayed in the notification
        Bitmap bmp = BitmapFactory.decodeResource(Res.getResources(),
                getApplicationInfo().icon);

        // make a notification Object, some of my code in parameters 
        mNotification = new NotificationCompat.Builder(this)
                .setTicker(Res.string(R.string.notification_ticker))
                .setContentTitle(Res.string(R.string.notification_title))
                .setContentText(Res.string(R.string.notification_txt_small))
                .setSmallIcon(R.drawable.dummyicon)
                .setLargeIcon(bmp)
                .setAutoCancel(true)
                .setPriority(Notification.PRIORITY_LOW)
                .setContentIntent(
                        PendingIntent.getActivity(this, 0, i,
                                PendingIntent.FLAG_UPDATE_CURRENT))
                .setStyle(
                        new NotificationCompat.BigTextStyle().bigText(Res
                                .string(R.string.notification_txt_big)))
                .setWhen(System.currentTimeMillis()).build();

        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
            mNotification.priority = Notification.PRIORITY_MIN;
        }


    } 

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        // this should do the trick
        startForeground(notificationId, mNotification);

        // should return START_STICKY
        return START_STICKY;

    } 

    // stop your service from being in the foreground, call this 
    // before stopping the service
    public void stopForeground() {
        notificationId++;
        stopForeground(true);
    }

}