4

Ich weiß, dass diese Frage schon einmal gestellt wurde, aber ich habe über alle Antworten, die ich finden konnte und noch nicht das Problem lösen konnte.OnHandleIntent() nicht in IntentService

Das Problem ist, dass beim Starten von BroadcastReceiver der IntentService onHandleIntent() nicht aufgerufen wird. Seltsamerweise läuft der Konstruktor (wie ich an der Log-Ausgabe sehen kann). Dies ist mein Code:.

NoLiSeA.class (Diese Klasse enthält die BroadcastReceiver, dass mein Dienst gestartet wird)

public void toProcess(StatusBarNotification sbn) { 
    LocalBroadcastManager.getInstance(this).registerReceiver(notificationForwarder, new IntentFilter("to_forward")); 
    Intent intent = new Intent("to_forward"); 
    intent.putExtra("sbn", sbn); 
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent); 
    Log.i("NoLiSe.TAG", "toProcess"); 
} 

private BroadcastReceiver notificationForwarder = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
      Log.i("NoLiSe.TAG", "BroadCastReceiver.onReceive"); 
      Intent i = new Intent(context, CoreTwoA.class); 
      i.putExtras(intent); 
      startService(i); 
     } 
    } 
}; 

CoreTwoA.class (Dies ist die IntentService onHandleIntent() ist nicht angerufen, wie ich sehen kann, weil kein Log-Text in der Konsole vorhanden ist.)

public class CoreTwoA extends IntentService { 

    private TextToSpeech mtts; 

    public CoreTwoA() { 
     super("TheCoreWorker"); 
     Log.d("source", "exception", new Exception()); 
     Log.i("CoreTwoA.TAG", "Constructor"); 
    } 

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

    } 
} 

AndroidManifest.xml

<service 
     android:name=".CoreTwoA" 
     android:label="@string/service_name" 
     android:exported="false"> 
    </service> 

UPDATE

auf Diskussionen unter So basiert, konnte ich das Problem auf die folgende Codezeile in der BroadCastReceiver verengen:

i.putExtra("sbn", sbn) 

Wenn ich es entferne, dh keine Extras zu der Absicht hinzufügen, dann wird meine onHandleIntent() Methode in meinem IntentService ausgeführt.

Wenn es enthalten ist, onHandleIntent() nicht ausgeführt wird und die folgenden von der Log.d() im Konstruktor meines IntentService zu logcat geschrieben

06-10 19:40:35.355 25094-25094/com.dezainapps.myapp D/source: exception 
                     java.lang.Exception 
                      at com.dezainapps.myapp.CoreTwoA.<init>(CoreTwoA.java:20) 
                      at java.lang.Class.newInstance(Native Method) 
                      at android.app.ActivityThread.handleCreateService(ActivityThread.java:2859) 
                      at android.app.ActivityThread.-wrap4(ActivityThread.java) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1427) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:148) 
                      at android.app.ActivityThread.main(ActivityThread.java:5417) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
06-10 19:40:35.355 25094-25094/com.dezainapps.myapp I/CoreTwoA.TAG: Constructor 

Irgendwelche Ideen, warum ein StatusBarNotification Objekt übergeben , das Parcelable implementiert, zu einem IntentService über einen Intent funktioniert nicht? Seltsam genug funktioniert das Broadcasting der gleichen StatusBarNotfication sbn Objekt von meiner ToProcess() -Methode über eine Absicht (siehe Code).

+2

Haben Sie in einem Protokoll überprüft, dass 'notificationForwarder' tatsächlich ausgeführt wird? Vielleicht hast du vergessen, den Empfänger zu registrieren. Der Dienst wird nicht gestartet, wenn 'onStartCommand' nicht ausgeführt wird oder umgekehrt. Sie können auch 'Log.d (" source "," ", new Exception())' im Konstruktor verwenden, um herauszufinden, was es erzeugt. – zapl

+0

@zapl So habe ich die Log.d() zum Konstruktor hinzugefügt und jetzt erhalte ich die oben genannte Ausnahme. Allerdings verstehe ich die Ausnahme nicht. Würde mich über Hilfe freuen. Danke für den guten Vorschlag. – REG1

+0

@AADTechnical Ich habe die Methode hinzugefügt, die den Broadcast sendet – REG1

Antwort

0

Haben Sie versucht, context.startService (intent) ;?

Wenn Sie in einem Rundfunkempfänger wie diesem sind, haben Sie keinen eigenen Kontext zum Nachschlagen. Ich glaube, Sie müssen also den an die onRecieve-Methode übergebenen verwenden.

+0

Ich habe es in context.startService (intent) geändert; aber daran änderte sich nichts. – REG1

0

verwenden:

private BroadcastReceiver notificationForwarder = new BroadcastReceiver() { 
@Override 
public void onReceive(Context context, Intent intent) { 
     Log.i("NoLiSe.TAG", "BroadCastReceiver.onReceive"); 
     Intent i = new Intent(context, CoreTwoA.class); 
     i.putExtra("intent",intent); 
     context.startService(i); 
    } 
} 

};

+0

Um nichts unversucht zu lassen, habe ich das versucht, aber es ändert nichts. – REG1

0

Verwenden Sie den folgenden Code:

private BroadcastReceiver notificationForwarder = new BroadcastReceiver() { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
      Log.e("NoLiSe.TAG", "BroadCastReceiver.onReceive"); 
      Intent i = new Intent(context, CoreTwoA.class); 
      i.putExtra("sbn",intent.getParcelableExtra("sbn")); 
      startService(i); 
     } 
    }; 

Sie falsch i.putExtras(intent); verwenden, die ich entnommen und auf andere Weise die StatusBarNotification Objekt durch putExtra zu senden.

ich diesen Code getestet und onHandleIntent

+0

Ok, also kopiere ich und steckte deinen Code und es ruft onHandleIntent auf, so dass es funktioniert. Aber jetzt hat die Absicht keine Extras. Wie sende ich per StatusBarNotification sbn als extra? Ich habe versucht, 'StatusBarNotfication sbn = intent.getParcelableExtra (" sbn "); i.putExtra ("sbn", sbn); ' zu Ihrem Code, aber dann seltsamerweise onHandleIntent wird nicht aufgerufen, also zurück zum alten Problem wieder. Irgendwelche Ideen? Danke, dass Sie wenigstens sicher gestellt haben, dass mein IntentService einigermaßen funktioniert. – REG1

+0

@ REG1 das ist, was wir tun müssen 'i.putExtra (" sbn ", intention.getParcelableExtra (" sbn "));' Hier verwenden wir die putExtra API, die 2. Parameter als Parcelable nimmt. 'putExtra (String name, Parcelable value)' Wieder habe ich das versucht und ich konnte onHandleIntent sehen – AADProgramming

+0

Also mache ich genau so, wie du sagst: 'i.putExtra (" sbn ", intent.getParcelableExtra (" sbn ");' wo 'sbn' vom Typ StatusBarNotification ist, aber für mich onHandleIntent() nicht aufgerufen wird. Außerdem habe ich versucht, meinen Dienst direkt von meiner ToProcess() -Methode zu starten und seinen StatusBarNotfication sbn-Parameter als mein Extra für die Absicht zu verwenden – REG1

1

ich das gleiche Problem wie die OP nicht nennen hatte.

Die Frage stellte sich heraus, dass ich (von etwa 4000 Parcelable Elemente) über die Intent eine riesige ArrayList vorging, die die IntentService beginnt. Es war extrem schwierig zu diagnostizieren, da es auf dem Gerät eines Kunden "unbemerkt" fehlte, so dass ich keinen ACRA-Fehlerbericht erhielt.

Wie auch immer, ich benutzte einen schnellen und schmutzigen Trick, um das Problem zu beheben - im Grunde um die ArrayList in einem statischen Element zu speichern, die ich verwendet, um die ArrayList zu setzen und nicht durch die Absicht zu übergeben.

Bei weiterer Untersuchung (einige Tests andere Geräte) fand ich eine TransactionTooLargeException geworfen. More discussion on that here.

Hier ist mein Test-Code, wenn jemand replizieren möchten:

Prüfregeln

Wenn Sie es Arbeit machen wollen, ändern Sie den 4000 Wert auf etwas viel kleiner.

ArrayList<ParcelableNameValuePair> testArrayList = new ArrayList<>(); 
for (int i = 0; i < 4000; i++) { 
    testArrayList.add(new ParcelableNameValuePair("name" + i, "value" + i)); 
} 
TestIntentService.startAction(AdminHomeActivity.this, testArrayList); 

TestIntentService.java

public class TestIntentService extends IntentService { 

    private static final String LOG_TAG = TestIntentService.class.getSimpleName(); 

    private static final String TEST_ACTION = "com.example.action.FOO"; 

    private static final String EXTRA_PARAM1 = "com.example.extra.PARAM1"; 
    private static final String EXTRA_PARAM2 = "com.example.extra.PARAM2"; 

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

    public static void startAction(Context context, ArrayList<ParcelableNameValuePair> testArrayList) { 

     Log.d(LOG_TAG, "1. startAction()"); 
     Utilities.makeToast(context, "1. startAction()"); 

     try { 
      int arrayListSize = (testArrayList == null) ? -1 : testArrayList.size(); 
      Log.d(LOG_TAG, "2. arrayListSize: " + arrayListSize); 
      Utilities.makeToast(context, "2. arrayListSize: " + arrayListSize); 

      Intent intent = new Intent(context, TestIntentService.class); 
      intent.setAction(TEST_ACTION); 
      //intent.putExtra(EXTRA_PARAM1, testArrayList); 
      intent.putParcelableArrayListExtra(EXTRA_PARAM2, testArrayList); 

      /** 
      * This line should result in a call to onHandleIntent() but, if we're sending a huge ArrayList, it doesn't... 
      */ 
      context.startService(intent); 
     } 
     catch(Exception e) { 
      Log.e(LOG_TAG, "Exception starting service", e); 
      Utilities.makeToast(context, "Exception starting service: " + e); 
     } 
    } 

    @Override 
    protected void onHandleIntent(Intent intent) { 

     Log.d(LOG_TAG, "3. onHandleIntent()"); 
     Utilities.makeToast(getApplicationContext(), "3. onHandleIntent()"); 

     try { 
      if (intent != null) { 
       final String action = intent.getAction(); 
       if (TEST_ACTION.equals(action)) { 

        ArrayList<ParcelableNameValuePair> testArrayList = intent.getParcelableArrayListExtra(EXTRA_PARAM1); 
        int testArrayListSize = (testArrayList == null) ? -1 : testArrayList.size(); 
        Log.d(LOG_TAG, "4. testArrayListSize: " + testArrayListSize); 
        Utilities.makeToast(getApplicationContext(), "4. testArrayListSize: " + testArrayListSize); 

        ArrayList<ParcelableNameValuePair> testArrayList2 = intent.getParcelableArrayListExtra(EXTRA_PARAM2); 
        int testArrayList2Size = (testArrayList2 == null) ? -1 : testArrayList2.size(); 
        Log.d(LOG_TAG, "5. testArrayList2Size: " + testArrayList2Size); 
        Utilities.makeToast(getApplicationContext(), "5. testArrayList2Size: " + testArrayList2Size); 

       } 
      } 
     } 
     catch(Exception e) { 
      Log.e(LOG_TAG, "Exception handling service intent", e); 
      Utilities.makeToast(getApplicationContext(), "Exception handling service intent: " + e); 
     } 
    } 

} 

ParcelableNameValuePair.java

public class ParcelableNameValuePair implements Parcelable { 

    private String name, value; 

    public ParcelableNameValuePair(String name, String value) { 
     this.name = name; 
     this.value = value; 
    } 

    public String getName() { 
     return name; 
    } 

    public String getValue() { 
     return value; 
    } 

    @Override 
    public int describeContents() { 
     return 0; 
    } 

    @Override 
    public void writeToParcel(Parcel out, int flags) { 
     out.writeString(name); 
     out.writeString(value); 
    } 

    public static final Parcelable.Creator<ParcelableNameValuePair> CREATOR = new Parcelable.Creator<ParcelableNameValuePair>() { 
     public ParcelableNameValuePair createFromParcel(Parcel in) { 
      return new ParcelableNameValuePair(in); 
     } 

     public ParcelableNameValuePair[] newArray(int size) { 
      return new ParcelableNameValuePair[size]; 
     } 
    }; 

    private ParcelableNameValuePair(Parcel in) { 
     name = in.readString(); 
     value = in.readString(); 
    } 

} 

Wie ich sagen, habe ich eine schnelle und schmutzige Lösung, um dieses Problem zu bekommen. Ich denke, eine bessere Lösung wäre für die App, die ArrayList in das Dateisystem zu schreiben, dann einen Verweis auf diese Datei (zB Dateiname/Pfad) über die Absicht an die IntentService übergeben und dann lassen Sie die IntentService den Inhalt der Datei abrufen und konvertieren es zurück zu einem ArrayList.

Wenn die IntentService mit der Datei gemacht hat, sollte es entweder löschen oder die Anweisung zurück in die App über eine lokale Broadcast-Pass, die Datei zu löschen, die es erstellt (vorbei an der gleichen Dateireferenz zurück, die geliefert wurde es).