【问题标题】:android running service starts app autmaticallyandroid运行服务自动启动
【发布时间】:2016-06-09 14:18:51
【问题描述】:

在我的应用程序中,我启动了一项服务以在应用程序处于后台时接收通知 - 此服务强制我的应用程序在我停止后自动启动。我试图通过使用未决意图来解决问题,但它仍然会发生。

这是我启动服务的意图:

Intent messageReceivingIntent = new Intent(this, MessageReceivingService.class);
messageReceivingIntent.putExtra("myUserId", myUserId);
Pending Inten messagePendingIntent = PendingIntent.getService(this, 0, messageReceivingIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    try {
        // Perform the operation associated with our pendingIntent
        messagePendingIntent.send();
    } catch (PendingIntent.CanceledException e) {
        e.printStackTrace();
    }

如果我通过 externalreceiver 调用服务,我会得到一个空指针异常。知道为什么吗?

这是我的 BroadcastReceiver 调用:

messageReceivingIntent = new Intent(this, MessageReceivingService.class);
messageReceivingIntent.putExtra("myUserId", myUserId);
messageReceivingIntent.setAction("com.example.androidtest");
sendBroadcast(messageReceivingIntent);

这是我的广播接收器:

public class ExternalReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    if(intent!=null){
        Bundle extras = intent.getExtras();
        if(!MapsActivity.inBackground){
            MessageReceivingService.sendToApp(extras, context);
        }
        else{
            MessageReceivingService.saveToLog(extras, context);
        }
    }
}

}

这是消息接收服务

public class MessageReceivingService extends Service {
private GoogleCloudMessaging gcm;
public static SharedPreferences savedValues;

public static final String INSTANCE_ID_SCOPE = "GCM";
final String BASE_URL = "http://www.example.com/";

public String myUserId;
public String registeredUserId;
public String token;
static PendingIntent pendingIntent;


public static void sendToApp(Bundle extras, Context context) {
    Intent newIntent = new Intent();
    newIntent.setClass(context, MapsActivity.class);
    newIntent.putExtras(extras);

    ShortcutBadger.applyCount(Content.getAppContext(), 0);

    newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(newIntent);
}

public void onCreate() {
    super.onCreate();
    final String preferences = getString(R.string.preferences);
    savedValues = getSharedPreferences(preferences, Context.MODE_PRIVATE);
    // In later versions multi_process is no longer the default
    if (VERSION.SDK_INT > 9) {
        savedValues = getSharedPreferences(preferences, Context.MODE_MULTI_PROCESS);
    }
    gcm = GoogleCloudMessaging.getInstance(getBaseContext());






    // Let AndroidMobilePushApp know we have just initialized and there may be stored messages
    sendToApp(new Bundle(), this);
}

protected static void saveToLog(Bundle extras, Context context) {
    SharedPreferences.Editor editor = savedValues.edit();
    String numOfMissedMessages = context.getString(R.string.num_of_missed_messages);
    int linesOfMessageCount = 0;

    for (String key : extras.keySet()) {
        String line = String.format("%s=%s", key, extras.getString(key));
        editor.putString(key, line);
        linesOfMessageCount++;
    }
    editor.putInt(context.getString(R.string.lines_of_message_count), linesOfMessageCount);
    editor.putInt(context.getString(R.string.lines_of_message_count), linesOfMessageCount);
    editor.putInt(numOfMissedMessages, savedValues.getInt(numOfMissedMessages, 0) + 1);
    editor.commit();

    String type = extras.getString("model");
    String id = extras.getString("id");
    String userId = extras.getString("user_id");

    //postNotification(new Intent(context, MapsActivity.class), context);
    if(type != null) {
        if (type.equals("content")) {
            Intent contentIntent = new Intent(context, ContentDetailActivity.class);

            Log.v("userID", userId);

            contentIntent.putExtra("contentId", id);
            if (userId != null) {
                contentIntent.putExtra("userId", userId);
            }

            postNotification(contentIntent, context);
        } else if (type.equals("user")) {
            Intent userIntent = new Intent(context, ProfileActivity.class);
            userIntent.putExtra("userId", id);

            postNotification(userIntent, context);
        }
    } else {
        postNotification(new Intent(context, NotificationsActivity.class), context);
    }

    ShortcutBadger.applyCount(Content.getAppContext(), Integer.valueOf(savedValues.getInt(Content.getAppContext().getString(R.string.num_of_missed_messages), 0)));
}

protected static void postNotification(Intent intentAction, Context context) {
    final NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

    pendingIntent = PendingIntent.getActivity(context, 0, intentAction, PendingIntent.FLAG_UPDATE_CURRENT);

    int numOfMissedMessages = 0;
    String missedMessage = "";
    if(savedValues != null){
        missedMessage = savedValues.getString("message", "nothing there");
    }



    Log.v("NUMOFMISSEDMESSAGES", String.valueOf(numOfMissedMessages));

    final Notification notification = new NotificationCompat.Builder(context).setSmallIcon(R.drawable.ic_launcher)
            .setContentTitle(missedMessage.substring(missedMessage.indexOf("=") + 1, missedMessage.length()))
            .setContentText("")
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)
            .build();
    mNotificationManager.notify(R.string.notification_number, notification);
}

private void register() {
    new AsyncTask() {
        protected Object doInBackground(final Object... params) {

            try {
                String instanceId = InstanceID.getInstance(getApplicationContext()).getId();
                //token = gcm.register(getString(R.string.project_number));
                token = InstanceID.getInstance(getApplicationContext()).getToken(getString(R.string.project_number), INSTANCE_ID_SCOPE);
                Log.i("registrationId", token);
            } catch (IOException e) {
                Log.i("Registration Error", e.getMessage());
            }
            return true;
        }

        @Override
        protected void onPostExecute(Object o) {
            super.onPostExecute(o);
            new SendRegUserId().execute();
        }
    }.execute();
}

public IBinder onBind(Intent arg0) {
    return null;
}
}

【问题讨论】:

  • 您使用的是Broadcast Receiver吗?
  • 您在Service 中使用了大量静态变量。这可能是您遇到麻烦的原因。如果您收到NullPointerException,请发布错误消息,包括来自 logcat 的堆栈跟踪,并解释当时发生了什么。另外,从您的ServiceonStartCommand() 发布代码

标签: android service push-notification android-pendingintent


【解决方案1】:

使用Broadcast Receiver 接收通知,然后将其发送到您的Service。这将允许您在不启动您的应用程序的情况下向用户发送notification

=========
编辑 1:

所以你的广播接收器需要启动服务而不是调用它的方法。因此,在您检查意图为空之后,类似于以下内容:

    ComponentName comp = new ComponentName(context.getPackageName(), YourIntentService.class.getName());
    startWakefulService(context, (intent.setComponent(comp));
    setResultCode(Activity.RESULT_OK);

另外,如果您在手机关机后仍想接收通知,您的Broadcast Receiver 应该扩展WakefulBroadcastReceiver

另外,您的Service 应该是IntentService。我认为 Android Studio 实际上带有一些预制的 GCM 类或 GCM 应用程序,它们实际上可以解决您遇到的 90% 的这些小问题。这是一个更好的起点。

查看GCM docs 以获得更多帮助。

【讨论】:

  • 我已经在 gcm 上苦苦挣扎了很长时间,并且遇到了问题。我很想修复给定的代码,因为除了自启动问题之外它运行良好。我很绝望
  • 说真的,请查看github.com/googlesamples/google-services/tree/master/android/… 并考虑将您的用例集成到该示例中 - 它是开箱即用的,将为您省去很多麻烦。 GCM 总是在变化(现在是 Firebase),我不得不在每次迭代中手动更新代码,这不是我推荐的做事方式
【解决方案2】:

一些可能的解决方案-

1) 使用广播接收器

2) 使用 onPause()、onResume() 方法

 SharedPreferences prefs=PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

 Intent messageReceivingIntent = new Intent(this,MessageReceivingService.class);

  onCreate(){

   //YOUR OWN CODE
   prefs.getBoolean("service_started",false);
 }

 onPause(){

 //YOUR OWN CODE
 prefs.edit().putBoolean("service_started",true).apply(); 
 startService(messageReceivingIntent);
}

onResume(){

 //YOUR OWN CODE
if(prefs.getBoolean("service_started",false)){
  stopService(new Intent(this, MessageReceivingService.class));
  prefs.edit().putBoolean("service_started",false).apply();
 }
}

3) 或者根据我的说法,最好的做法是实施 Firebase 云消息传递以进行通知。

看看https://firebase.google.com/docs/cloud-messaging/

它大大减少了您的电池和服务器工作量。它是 Google 的一项全新服务。

或者我认为您的服务代码中可能存在错误

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-01
    • 2019-11-24
    • 2016-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-27
    • 1970-01-01
    相关资源
    最近更新 更多