App startet willkürlich

impidan

impidan

Dauergast
122
Mahlzeit.

Ich hab ein interessantes Problem. "Meine" App kommt willkürlich, manchmal im Sekundentakt, manchmal stundenlang gar nicht wieder in den Vordergrund. Dass das nervt und keine Absicht ist, ist soweit klar.

Das Problem ist, das für Push Nachrichten die Amazon Web Services verwendet werden. Amazon hat da keine "Doku" zu, sondern eine Beispiel App. Weil es schnell gehen musste, habe ich diese Beispiel App quasi erweitert, ABER, und jetzt wird es interessant, diese Beispiel-App verhält sich schon genau so...

Im Log steht immer nur:

03-05 07:54:32.876: I/ActivityManager(780): Start proc de.meinpackage.app for service de.meinpackage.app/.MessageReceivingService: pid=30865 uid=10368 gids={50368, 3003, 5012}

und danach startet die app genau gleich, wie wenn ich sie selbst starte.

hat jemand ne spontane idee?

Danke!
 
Naja "App Starten" ist ne komische aussage....

was genau startet? Ne Activity, nen Service?

Klingt so als würdest du ne Activity beim erhalten von Push Nachrichten starten oO

lg. Dagobert
 
Also, bei der Beispiel app ist das so:

Der Service "MessageReceivingService" der ja auch in meinem Log-Auszug aufgerufen wird, sieht so aus:

package de.meinpackage.app;

import java.io.IOException;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Build.VERSION;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.google.android.gms.gcm.GoogleCloudMessaging;

/*
* This service is designed to run in the background and receive messages from gcm. If the app is in the foreground
* when a message is received, it will immediately be posted. If the app is not in the foreground, the message will be saved
* and a notification is posted to the NotificationManager.
*/
public class MessageReceivingService extends Service{
private GoogleCloudMessaging gcm;
public static SharedPreferences savedValues;

public static void sendToApp(Bundle extras, Context context){
Intent newIntent = new Intent();
newIntent.setClass(context, AndroidMobilePushApp.class);
newIntent.putExtras(extras);
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());
SharedPreferences savedValues = PreferenceManager.getDefaultSharedPreferences(this);
if(savedValues.getBoolean(getString(R.string.first_launch), true)){
register();
SharedPreferences.Editor editor = savedValues.edit();
editor.putBoolean(getString(R.string.first_launch), false);
editor.commit();
}
// 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("MessageLine" + linesOfMessageCount, 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();
postNotification(new Intent(context, AndroidMobilePushApp.class), context);
}

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

final PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intentAction, Notification.DEFAULT_LIGHTS | Notification.FLAG_AUTO_CANCEL);
final Notification notification = new NotificationCompat.Builder(context).setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Message Received!")
.setContentText("")
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.getNotification();

mNotificationManager.notify(R.string.notification_number, notification);
}

private void register() {
new AsyncTask(){
protected Object doInBackground(final Object... params) {
String token;
try {
token = gcm.register(getString(R.string.project_number));
Log.i("registrationId", token);
}
catch (IOException e) {
Log.i("Registration Error", e.getMessage());
}
return true;
}
}.execute(null, null, null);
}

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

}

Sofern ich das richtig sehe, startet dieser ja die Activity AndroidMobilePushApp wenn er in "protected static void saveToLog(Bundle extras, Context context)" reingeht.

Wie gesagt, die bereitgestellte Beispiel-App verhält sich hier schon falsch, oder komisch. Und ich weiß einfach nicht wieso, da das ganze von Amazon wenig bis gar nicht dokumentiert ist.

Hier der Link zur Amazon Beispiel-App:
http://docs.aws.amazon.com/sns/latest/dg/samples/snsmobilepush.zip

Sowie zu der "Doku"
Getting Started with Google Cloud Messaging for Android - Amazon Simple Notification Service

Sitze da schon etliche Stunden drüber, letztendlich auch viel mit try and error.. aber das kanns ja nicht sein.

Danke!
 
Wir reden hier von amazon's sns richtig?

vllt. solltest du dir mal bei der Android Doku ansehen wie Push-Clients richtig implementiert werden ;)

In
Code:
sendToApp(...)
Wird eine Activity gestartet...

und ein bisschen Formatierung für dem ganzen auch nicht schaden^^

lg. Dagobert
 
Zuletzt bearbeitet:
  • Danke
Reaktionen: impidan
Die formatierung ist bei dem paste hier verloren gegangen, und wie gesagt das ist 1:1 das Beispiel von Amazon SNS.

Das verwenden von dem Amazon Dienst war nicht meine Wahl leider, ich bin nur der, der es ausbaden muss.

@sendToApp:

Ja, sehe ich. Meinst du das ist der "Fehler"? Weil gewollt kann das doch nicht sein, das die App immer und immer wieder anspringt?
 
Also zunächst halte ich es für kontraproduktiv eine Demo als Vorlage zu nehmen ohne ggf. alles (nagut, man muss nicht alles verstehen, aber großteil...) zu verstehen.

Der einzige Intent, der eine Activity startet wurde genannt (und zwar der in sendToApp). sendToApp wird immer im onCreate aufgerufen.

Fazit? Offensichtlich startet der Service neu. Zum Beispiel, weil er (vom System) gekillt wurde und neu angestoßen wird.
 
  • Danke
Reaktionen: impidan
Natürlich kann das gewollt sein... ist ja nur nen Beispiel :winki:
Naja Amazons SNS macht ja nur die Server Verbindung einfacher....
Ich habe letztes Jahr auch mal nen SNS angebunden in Android
GcmBroadcastReceiver:
Code:
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
    private static final String TAG = GcmBroadcastReceiver.class.getSimpleName();

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i(TAG, "onReceive()");
        final ComponentName comp = new ComponentName(context.getPackageName(),
                GcmIntentService.class.getName());
        // Start the service, keeping the device awake while it is launching.
        startWakefulService(context, (intent.setComponent(comp)));
        setResultCode(Activity.RESULT_OK);
    }
}
GcmIntentService
Code:
public class GcmIntentService extends IntentService implements DataListCallback<Message> {
    private static final String TAG = GcmIntentService.class.getSimpleName();
    public static final String NOTIFICATION_EVENT = "notification_event";
    public static final String NOTIFICATION_ID = "notification_id";

    private NotificationManagerCompat nManager;
    private NotificationCompat.Builder nBuilder;
    private DataBaseHelper dbHelper;
    private int notificationId;

    public GcmIntentService() {
        super("GcmIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.v(TAG, "onHandleIntent()");

        final SharedPreferences prefs = getSharedPreferences(ZoogetherApplikation.class.getSimpleName(), Context.MODE_PRIVATE);
        final boolean isNotificationEnable = prefs.getBoolean("push", true);
        Log.v(TAG, "is push enable: " + isNotificationEnable);
        if (!isNotificationEnable) {
            return;
        }
        
        nManager = NotificationManagerCompat.from(this);
        nBuilder = new NotificationCompat.Builder(this);
        //FIXME von Application holen
        dbHelper = DataBaseHelper.getInstance(this);

        final Bundle extras = intent.getExtras();
        final GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
        final String messageType = gcm.getMessageType(intent);

        if (!extras.isEmpty() && GoogleCloudMessaging.
                MESSAGE_TYPE_MESSAGE.equals(messageType)) {
            Log.d(TAG, "Received: " + extras.toString());
            final String petIdString = extras.getString("PetID");
            final long petId = Long.parseLong(petIdString);
            final User user = dbHelper.getUser();
            if (user == null) {
                return;
            }
            final long userId = user.getId();
            final Pet currentPet = dbHelper.getPet(petId);
            Log.d(TAG, "currentPet: " + currentPet);
            notificationId = PetUtil.getNotificationId(dbHelper, petId);
            Log.d(TAG, "NotificationId: " + notificationId);
            final ImageHelper imageHelper = ((ZoogetherApplikation) getApplication()).getImageHelper();
            final Bitmap profileImage = imageHelper.loadProfileBitmap(currentPet.getId(), currentPet.getSpecie());
            nBuilder.setContentTitle(currentPet.getName()).setContentText(getString(R.string.wrote_something)).setSmallIcon(R.drawable.ic_notification)
                    .setTicker(currentPet.getName() + getString(R.string.wrote_something)).setAutoCancel(true)
                    .setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE).setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
            Intent resultIntent = new Intent(this, MainActivity.class);
            intent.putExtra("petId", petId);
            TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
            stackBuilder.addParentStack(MainActivity.class);
            stackBuilder.addNextIntent(resultIntent);
            PendingIntent resultPendingIntent =
                    stackBuilder.getPendingIntent(
                            0,
                            PendingIntent.FLAG_UPDATE_CURRENT
                    );
            nBuilder.setContentIntent(resultPendingIntent);
            if (profileImage != null) {
                nBuilder.setLargeIcon(profileImage);
            }
            final long timestamp = dbHelper.getLatestMessageTime(petId);
            new AuthNetworkBackgroundTask(UrlFactory.getMessagesUrl(this, userId, petId, timestamp), new ServiceMessageResponseHandler(this, this)).execute();
        }
    }

    @Override
    public void onSuccess(List<Message> messages) {
        Log.v(TAG, "onSuccess()");
        try {
            dbHelper.writeInDb(messages);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        nManager.notify(notificationId, nBuilder.build());
        sendLocalBroadcast(notificationId);
    }

    private void sendLocalBroadcast(final int notificationId) {
        Intent intent = new Intent(NOTIFICATION_EVENT);
        intent.putExtra(NOTIFICATION_ID, notificationId);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }

    @Override
    public void onError(int resId) {
        Log.v(TAG, "onError()");
        nManager.notify(notificationId, nBuilder.build());
        sendLocalBroadcast(notificationId);
    }

Meins sieht so aus (denk dir den Käse den du nicht brauchst weg ;))
Ich habe mich dabei an die aktuelle GCM implementierung der Play-Services gehalten...

lg. Dagobert
 
  • Danke
Reaktionen: impidan
Danke euch beiden schonmal. Natürlich ist es nicht ratsam oder sinnvoll sich an die Demo zu halten. Aber (wer kennt es nicht) der Zeitdruck.

Eigentlich hat die App UrbanAirship benutzt, aber da die App solange zeit nicht benötigt und genutzt wurde, hat ja UrbanAirship mittlerweile den Gratisservice eingestellt und schied somit aus, also sollte es jetzt Amazon SNS sein. Bei UA war alles schön dokumentiert und hat auch 1a geklappt, bei Amazon steh ich etwas auf dem Schlauch.

Soweit macht die App was sie soll, ausser diese nervigen restarts. Kann ich nicht "einfach"

public static void sendToApp(Bundle extras, Context context){
Intent newIntent = new Intent();
newIntent.setClass(context, AndroidMobilePushApp.class);
newIntent.putExtras(extras);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(newIntent);
}

hier die letzte Zeile rausnehmen, sodass die Activity nicht mehr gestartet wird? Oder sollte ich lieber Dagoberts Methode nehmen und die Standart GCM Methode verwenden (und quasi alles neu machen)
 
Hör auf die schuld auf den SNS zu schieben :scared:

Der hat damit mal gar nichts zu tun... oO Der macht genau das was er soll... dir Push-Nachrichten schicken... dein GCM client ist einfach Fehlerhaft.

lg.
 
  • Danke
Reaktionen: impidan
Okay :D

dann anders Formuliert, der von AWS beispielhaft mitgesendete Demo-GCN-Client verhält sich seltsam, wie treib ich dem das aus, mit wenig aufwand :D

EDIT: habe gerade das hier gesehen, als ich den fehler reproduzieren wollte:
03-05 11:35:13.054: W/ActivityManager(772): Scheduling restart of crashed service de.meinpackage.app/.MessageReceivingService in 4000ms

EDIT2: habe auf onStop() jetzt stopService() gemacht, das sorgt jetzt korrekterweise dafür das der Service gestoppt wird. Allerdings habe ich jetzt das nächste Problem.

Wenn ich die App per Taskmanager beende, und dann eine Push Nachricht sende, gibt es einen Force Close, mit folgender Fehlermeldung:
03-05 12:40:28.401: E/AndroidRuntime(22408): FATAL EXCEPTION: main
03-05 12:40:28.401: E/AndroidRuntime(22408): Process: de.meinpackage.app, PID: 22408
03-05 12:40:28.401: E/AndroidRuntime(22408): java.lang.RuntimeException: Unable to start receiver de.meinpackage.app.ExternalReceiver: java.lang.NullPointerException

ExternalReceiver:

Code:
public class ExternalReceiver extends BroadcastReceiver {
	
    public void onReceive(Context context, Intent intent) {
    	
        if(intent!=null){
            Bundle extras = intent.getExtras();
            if(!AndroidMobilePushApp.inBackground){
                MessageReceivingService.sendToApp(extras, context);
            }
            else{
                MessageReceivingService.saveToLog(extras, context);
            }
        }
    }

}

liegt das daran, das if intent = null nicht abgefangen wird?
 
Zuletzt bearbeitet:

Ähnliche Themen

Manny87
  • Manny87
Antworten
11
Aufrufe
166
swa00
swa00
R
  • Robby1950
2
Antworten
23
Aufrufe
1.016
Robby1950
R
netfreak
  • netfreak
Antworten
10
Aufrufe
461
netfreak
netfreak
Zurück
Oben Unten