Um ehrlich zu sein, hatte ich unter iOS nicht viel Referenzmaterial, also ich habe es selbst implementiert, aber für Android dieser Artikel war sehr hilfreich. Ich brauchte jedoch einige zusätzliche Kenntnisse darüber, was ich dieses Mal implementieren wollte, daher enthält dieser Artikel auch diese.
Zuallererst die Hauptaktivität. Dies ist ** nur eine Zeile, Themenzusatz ** für die FCM-Initialisierung. ** Wenn Sie es nicht einmal brauchen, brauchen Sie nichts **, aber dann können Sie keine Benachrichtigungen separat zwischen hier und der iOS-Versions-App senden.
MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FirebaseMessaging.getInstance().subscribeToTopic("TOPICNAME");
// other initializing...
}
Holen Sie sich als Nächstes das generierte / aktualisierte Geräte-Token. Dies ist wichtig, wenn Sie unterschiedliche Benachrichtigungen für unterschiedliche Geräte wünschen [^ 1], aber die genaue Zeit, zu der Sie dies tun können, ist "FirebaseInstanceIdService # onTokenRefresh". Sie können dies überschreiben und das Gerätetoken zu diesem Zeitpunkt an Ihren eigenen Server senden.
Diesmal muss ich jedoch nur Benachrichtigungen an alle Benutzer gleichzeitig senden können, und ich bin mir nicht sicher, ob ich den Dienst "FirebaseInstanceIdService" noch benötige. Wenn Sie es nicht brauchen, wird es wieder ** "Sie müssen nichts tun" ** sein. Da ich mich jedoch etwas unwohl fühlte, entschied ich mich, nur den Dienst laufen zu lassen, und stellte ihn so ein, dass die Superklasse direkt als Dienst gestartet wurde, ohne eine Unterklasse zu erstellen. Ist das okay?
AndroidManifest.xml
<service android:name="com.google.firebase.iid.FirebaseInstanceIdService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
Sogar in FCM GCM-Artikel, den ich in meinem vorherigen Job geschrieben habe (Kapitel "Tag, das Android-Benachrichtigungen automatisch überschreiben und aktualisieren kann") -2.html) hat die Aktualisierungsspezifikation nicht geändert ** "Wenn Sie Standardbenachrichtigungen unter Android / nur im Hintergrund erhalten, müssen Sie keinen Code schreiben" **. Diesmal müssen Sie aber auch die Benachrichtigung im Vordergrund behandeln. Dazu können Sie "FirebaseMessagingService # onMessageReceived" überschreiben und dies tun. Unter diesen können Sie denselben Inhalt wie die im Hintergrund angezeigte Benachrichtigung generieren und als ausstehende Absicht registrieren.
Ich meine, das ist @ kirimins Artikel Es ist fast dasselbe. Es ist nur ein dankbarer Regensturm (totes Wort). Es wird jedoch nur die Generierung der Absicht geändert, wenn auf die von diesem Code angezeigte Benachrichtigung getippt wird. Grundsätzlich ist diese Absicht in den In-Prozess gerutscht, oh, COM brain (und aus irgendeinem Grund, wenn Sie dies eingeben) Da es nur in der eigenen Anwendung verwendet wird und nicht im Pro-Less-Gehirn, in dem der Finger rutscht und nicht weniger schlägt, frage ich mich außerdem, ob die Zeichenkettenkonstante in "MainActivity" definiert und verwendet werden sollte. Das sind "MainActivity.ARG_FRAGMENT" und "MainActivity.PUSH_NOTIFICATION_ACTION".
FirMessagingService.java
public class FirMessagingService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Map<String, String> data = remoteMessage.getData();
if (data == null) {
return;
}
String fragment = data.get(MainActivity.ARG_FRAGMENT);
if (fragment == null) {
return;
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext());
builder.setSmallIcon(R.drawable.notification);
builder.setContentTitle(remoteMessage.getNotification().getTitle());
builder.setContentText(remoteMessage.getNotification().getBody());
builder.setDefaults(Notification.DEFAULT_SOUND
| Notification.DEFAULT_VIBRATE
| Notification.DEFAULT_LIGHTS);
builder.setAutoCancel(true);
//Ausstehende Absicht erstellen
Intent intent = new Intent(this, MainActivity.class);
intent.setAction(MainActivity.PUSH_NOTIFICATION_ACTION);
intent.putExtra(MainActivity.ARG_FRAGMENT, fragment);
PendingIntent contentIntent = PendingIntent.getActivity(
getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
//Benachrichtigungsanzeige
NotificationManagerCompat manager = NotificationManagerCompat.from(getApplicationContext());
manager.notify(0, builder.build());
}
}
Vergessen Sie natürlich nicht, diese Unterklasse als Dienst zu registrieren.
AndroidManifest.xml
<service android:name=".FirMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
Diesbezüglich funktioniert die Regelung "Startmodus ist Einzelaufgabe" äußerst effektiv, und es gibt nur zwei Muster, die beim Tippen auf eine Benachrichtigung auftreten können. (Beachten Sie, dass diese Regelung nichts mit FCM zu tun hat. Es ist eine übliche Methode, immer nur eine eigene Anwendung auf Android zu starten, und sie ist sehr verbreitet [^ 2].)
Aktivität | Wird beim Tippen aufgerufenAppCompatActivity Methode von |
Wie man eine Absicht bekommt |
---|---|---|
Während des Startvorgangs | onNewIntent |
onNewIntent Argumente von |
Nicht angefangen | onCreate |
getIntent Methode |
In beiden Fällen können Sie eine Absicht erhalten, die genau dieselben Informationen enthält, sodass Sie sie mit einer gängigen Methode verarbeiten können.
MainActivity.java
public static final String PUSH_NOTIFICATION_ACTION = "FCM";
public static final String ARG_FRAGMENT = "fragment";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FirebaseMessaging.getInstance().subscribeToTopic("TOPICNAME");
int fragmentId = onIntent(getIntent());
if (fragmentId == 0) {
//Ruft den ID-Wert des zuletzt angezeigten Fragments ab
fragmentId = PreferenceManager.getDefaultSharedPreferences(this).getInt(PreferenceKey.RECENT_FRAGMENT_POSITION, 0);
}
// other initializing
changeFragment(fragmentId, true);
}
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
changeFragment(onIntent(intent), false);
}
//Rufen Sie die ID des Fragments, das Sie anzeigen möchten, aus der Benachrichtigungsabsicht ab
//In dieser Implementierung für Benachrichtigungen{"fragment":"info"}Wenn der KV enthalten ist, versuche ich, den Infobildschirm anzuzeigen
//Wenn Sie Reflektion verwenden, benötigen Sie keine bedingte Verzweigung.(^^ゞ
private int onIntent(Intent intent) {
if (intent != null && "info".equals(intent.getStringExtra(ARG_FRAGMENT))) {
return R.id.info;
} else {
return 0;
}
}
//Einzigartige Methode zum Wechseln zu Fragment, angegeben durch fragmentId, falls vorhanden
//Wenn isFirst true ist, wird das Standardfragment angezeigt, wenn fragmentId 0 ist
//Wenn falsch, nichts tun
private void changeFragment(int fragmentId, boolean isFirst) {
//Geben wir unser Bestes
}
Stellen Sie dann den Absichtsfilter richtig ein, damit "MainActivity" die Absicht der Benachrichtigung empfangen kann. Der Grund wird später erklärt, aber der Aktionsname "FCM" muss dieselbe Zeichenfolge sein wie "MainActivity.PUSH_NOTIFICATION_ACTION" **.
AndroidManifest.xml
<activity android:label="@string/app_name" android:name=".MainActivity"
android:taskAffinity="com.wsf_lp.oritsubushi.map" android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="FCM" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Wenn Sie dies nicht nur auf der Anwendungsseite, sondern auch auf Ihrer eigenen Serverseite nicht richtig machen, werden Sie tatsächlich irgendwo in der Reihe der Bewegungen "Senden und Empfangen von Benachrichtigungen und Umschalten der Anzeige" stolpern.
Daher habe ich die Liste der Zeichenfolgenliterale, die bisher in der Codeserie veröffentlicht wurden, und ihre Bedeutung zusammengefasst.
String | Erscheinungsort | Bedeutung | Wo anwendbar |
---|---|---|---|
"FCM" | Manifest Hauptaktivität |
Absichtsaktionsname | Von der FCM-Benachrichtigungsnutzlastclick_action Der Wert desonMessageReceived Absicht erstellt mitonNewIntent Absicht weitergegeben anonCreate Im InnerengetIntent Absicht durch Anruf erhalten |
"fragment" | FirebaseMessagingService Hauptaktivität |
Name des Benutzerdatenschlüssels | Schlüsselname in der FCM-DatennutzlastonMessageReceived Schlüsselname in entfernten Daten, die mit abgerufen werden können |
"info" | FirebaseMessagingService Hauptaktivität |
Benutzerdatenwert | Von der FCM-Datennutzlast"fragment"Der Wert deronMessageReceived で取得できるリモートデータ内Der Wert der |
Es ist einfach zusammenzufassen, aber "FCM-Nutzdaten" werden in allen Elementen in der Tabelle angezeigt. In der Tat ist es am wichtigsten, die Nutzdaten auf Ihrem eigenen Server zu verstehen, die die an FCM zu sendenden Daten weiterleiten. Mit anderen Worten bedeutet dies auch, dass ** beim Verknüpfen des Betriebs der App mit Push-Benachrichtigungen das Auslassen von "Einfache Eingabe des Benachrichtigungsinhalts über den Benachrichtigungsbildschirm der Firebase-Konsole und Klicken (totes Wort)" nicht zulässig ist **. (In Anbetracht des später beschriebenen Symbolproblems ist die aktuelle Konsole natürlich von Anfang an unbrauchbar.)
In Bezug auf die FCM-Nutzlast ist sie im offiziellen Dokument aufgeführt, aber es reicht nicht aus, nur diese [alle Formate] zu verwenden. Es scheint wichtig zu sein, (https://firebase.google.com/docs/cloud-messaging/http-server-ref) richtig zu lesen.
In diesem Sinne sind hier die JSONs, die ich von meinem eigenen Server an den FCM-Server sende.
{
"to": "In der App registrierter Themenname",
"notification": {
"title": "Benachrichtigungstitel",
"body": "Benachrichtigungsstelle",
"click_action": "FCM",
"icon": "notification"
},
"data": {
"fragment": "info"
}
}
Das Wichtigste in FCM ist die "Benachrichtigung", die Benachrichtigungsnutzlast. Neben "title" und "body" ist "click_action" einer der Schlüssel. Dies ist genau der Wert der Aktion, die in der Android-Push-Benachrichtigungsabsicht enthalten ist [^ 3]. Und mit dem Wert dieser Aktion ist es die Einstellung des Absichtsfilters im Manifest, die verhindert, dass die Aktivität der App zusätzliche Absichten erhält. Daher müssen * die "click_action" der an den FCM-Server gesendeten Benachrichtigungsnutzdaten und der Aktionsname des im Manifest festgelegten Absichtsfilters mit * und * der vom Benutzer generierten Absicht übereinstimmen, die Benachrichtigung auch im Vordergrund anzuzeigen. Aktionsnamen müssen ebenfalls identisch sein *.
Andererseits sind die "Daten", die in FCM optional sind, dh die Datennutzlast, ein normales Wörterbuch. Und dies ist diejenige, die an die "RemoteMessage" übergeben wird, die vom Argument "FirebaseMessagingService # onMessageReceived" übergeben wird, und die auch durch das Argument "getIntent" oder "onNewIntent" erhalten wird, das in "onCreate" der Aktivität aufgerufen wird. Dies ist der Wert, der als Extra der beabsichtigten Absicht festgelegt wird. Also * müssen diese Schlüsselnamen übereinstimmen * und * Sie müssen denselben Wert als Extra mit demselben Schlüsselnamen in Ihre eigene generierte Absicht kopieren, um die Benachrichtigung auch im Vordergrund anzuzeigen. *.
Da es diesmal nicht internationalisiert wird, ist es außerdem so, als würde man Japanisch schreiben, wie es in "Titel" und "Körper" steht, aber wenn Internationalisierung notwendig ist GCM-Artikel in meinem vorherigen Job geschrieben (: //www.mate-en.com/techblog/google-cloud-messaging-2.html) sollte hilfreich sein.
Und wieder, obwohl nicht direkt mit dem Code verbunden. Unter Android kann ein Symbol in der Benachrichtigungsanzeige angezeigt werden. Und in älteren Versionen von GCM vor FCM wird "GCMListenerService # onMessageReceived" * immer * aufgerufen *, unabhängig davon, ob sich die App im Vordergrund oder im Hintergrund befindet * (daher muss "GCM ListerService" ein Dienst sein. (Ich habe es nicht getan), und ich habe die Benachrichtigungen immer selbst erstellt (nur im Prozess selbst in "onMessageReceived" im Vordergrund im aktuellen FCM). Natürlich konnte ich dort das Benachrichtigungssymbol setzen. Das neue GCM danach, das fast das aktuelle FCM ist, führte jedoch die Spezifikation ein, dass * im Hintergrund "onMessageReceived" nicht * genannt wird. Infolgedessen können Sie das Symbol nicht im Hintergrund einstellen. Um dies zu vermeiden, wurde der Schlüsselname "icon" zur Benachrichtigungsnutzlast von GCM hinzugefügt und auf den aktuellen FCM übertragen.
{
"notification": {
"icon": "notification"
}
}
Und dies ist auch eine Metamorphose, aber nehmen wir an, Sie setzen den Wert "Benachrichtigung" wie oben auf "Symbol". Dieser Wert von "Benachrichtigung" wurde auf der App-Seite "R.drawable.notification" zugeordnet. Natürlich ist dieses Symbol ein ID-Wert, und wenn das Symbol eine Bilddatei ist, insbesondere eine Datei mit dem Namen "res / drawable / notification.png " (natürlich wurde der Stoff durch Auflösung / SDK-Version / lokal usw. geteilt). (In Ordnern verteilt) wird als Symbol verwendet. Der Punkt ist, dass ** der Dateiname (ohne die Erweiterung) des PNG-Bildes für das Symbol der Wert des Symbols "Schlüssel" der Benachrichtigungsnutzlast ist **. Mit anderen Worten, um das Benachrichtigungssymbol anzuzeigen, können Sie normalerweise (viele!) Symbolbilder erstellen, diese entsprechend unter res / drawable / platzieren und den Dateinamen an den FCM-Server übergeben. Natürlich muss dasselbe Symbol in "onMessageReceived" gesetzt sein, damit die Benachrichtigung auch im Vordergrund angezeigt wird.
Dieses Gefühl, dass "die Zeichenfolge des Dateinamens im Java-Code zu einem Symbolnamen und beim Verweisen zu einem ganzzahligen Wert wird, beim Aufrufen vom Server jedoch mit einer Zeichenfolge angegeben wird", geht um und kehrt zum ursprünglichen Gefühl zurück .. Wie erwartet ist es Android (verbrannte Brust) [^ 4].
[^ 1]: Wenn es sich um eine SNS- oder Chat-App handelt, hängt der zu benachrichtigende Inhalt vom Benutzer ab. Daher werden die Gerätetoken des Benutzers und des Terminals (natürlich kann derselbe Benutzer mehrere Geräte verwenden, sodass RDB sie in der Tabelle n: m verwaltet) auf der eigenen Serverseite verknüpft, um einen bestimmten Benutzer zu benachrichtigen. Das Senden nur an alle Geräte dieses Benutzers ist erforderlich. Für die Benachrichtigung nur des Geräts dieses bestimmten Benutzers ist ein Geräte-Token erforderlich, und Android kann dieses Geräte-Token ändern. Bei jeder Änderung wird der eigene Server informiert. Muss sein.
[^ 2]: Ah, in der Win32-Ära wurde dies mit einem benannten Mutex durchgeführt ... Frühe Windows-Version Eclipse hat einfach zu oft auf das Symbol geklickt und mehrmals gestartet, um den Arbeitsbereich, einen dedizierten Launcher, nicht zu beschädigen Ich habe es mit CreateMutex
geschrieben ... (Aufgrund alter Augen, entfernter Augen)
[^ 3]: Übrigens ist "click_action", eine Schaltfläche, die angezeigt wird, wenn Sie eine Benachrichtigung unter iOS durchwischen (sofern die App dies unterstützt) = mit einer benutzerdefinierten Aktion verknüpft. Es ist ein Schlüssel, der von GCM geerbt wurde, aber es ist erstaunlich, dass er mit beiden Betriebssystemen kompatibel ist! Es ist ein Lob.
[^ 4]: Natürlich wäre es bei älteren Androiden, die über sehr schlechte Ressourcen verfügten, notwendig gewesen, Symbole in ganzzahlige Werte umzuwandeln und zu bauen. Und selbst in der heutigen Zeit, in der dies nicht der Fall ist, besteht der Vorteil, dass die Code-Vervollständigung von IDE problemlos funktioniert (selbst in früheren Zeiten wurde sie als schlechtes Know-how von VC ++ missbraucht, indem alles in eine mysteriöse Klasse gestopft wurde). Nein, aber ich bin auch der Meinung, dass ein wesentlicher Teil der Unangemessenheit der Win32-API darin besteht, dass sie von Win16 zu stark in Mitleidenschaft gezogen wurde, um den Code der OLE-Steuerelemente, die das Unternehmen intern für VB erstellt hat, kompatibel (oder eher böse) zu machen. Die Wurzel kann VB älter als Win16 sein ??), Android wird auch durch verschiedene Dinge wie die Einschränkung der Methode 64k gezogen (was zu einer Scala-Konvertierung führt, ist sehr schwierig) ... Ist es etwas, das auf jeden Fall eine Geschichte hat? ..
Recommended Posts