1

EDIT: es heraus - siehe Antwort untenGCM Mitteilung Empfänger/Token Registrierung

Ich versuche Registrierung Token, speichert sie in einem Server, und verwenden Sie dann die Token senden Push-Benachrichtigungen zu generieren. Zu diesem Zeitpunkt habe ich Registrierungstoken erfolgreich gesendet und gespeichert und sende Benachrichtigungen von einer Web-API, die jedoch nicht auf meinem Gerät ankommen. Ich frage mich, ob/was ich R.string.gcm_defaultSenderId mit ersetzen soll (d. H. Der Absender-Schlüssel von GCM?) Ich bin meinen Code für die Token-Registrierung sowie meine Benachrichtigung Listener unten enthalten.

public class GCMRegistrationIntentService extends IntentService { 

//Constants for success and errors 
public static final String REGISTRATION_SUCCESS = "RegistrationSuccess"; 
public static final String REGISTRATION_ERROR = "RegistrationError"; 

private Context context; 
private String sessionGUID = ""; 
private String userGUID = ""; 

//Class constructor 
public GCMRegistrationIntentService() { 
    super(""); 
} 

@Override 
protected void onHandleIntent(Intent intent) { 
    context = getApplicationContext(); 
    sessionGUID = RequestQueueSingleton.getInstance(context).getSessionGUID(); 
    userGUID = RequestQueueSingleton.getInstance(context).getUserGUID(); 
    //Registering gcm to the device 
    registerGCM(); 

} 

//Registers the device to Google Cloud messaging and calls makeAPICall to send the registration 
//token to the server 
private void registerGCM() { 
    //Registration complete intent initially null 
    Intent registrationComplete; 

    //declare a token, try to find it with a successful registration 
    String token; 
    try { 
     //Creating an instanceid 
     InstanceID instanceID = InstanceID.getInstance(this); 

     //Getting the token from the instance id 
     token = instanceID.getToken(getString(R.string.gcm_defaultSenderId), 
       GoogleCloudMessaging.INSTANCE_ID_SCOPE, null); 

     //Display the token, need to send to server 
     Log.w("GCMRegIntentService", "token:" + token); 

     String android_id = Settings.Secure.getString(context.getContentResolver(), 
       Settings.Secure.ANDROID_ID); 
     int osTypeCode = Constants.OST_ANDROID; 
     JSONObject parms = new JSONObject(); 
     try { 
      parms.put("deviceID", android_id); 
      parms.put("OSTypeCode", osTypeCode); 
      parms.put("token", token); 
     } catch (JSONException e) { 
      e.printStackTrace(); 
     } 

     Transporter oTransporter = new Transporter(Constants.TransporterSubjectUSER, 
       Constants.REGISTER_NOTIFICATION_TOKEN, "", parms, userGUID, sessionGUID); 
     oTransporter.makeAPICall(getApplicationContext(), ""); 

     //on registration complete. creating intent with success 
     registrationComplete = new Intent(REGISTRATION_SUCCESS); 

     //Putting the token to the intent 
     registrationComplete.putExtra("token", token); 
    } catch (Exception e) { 
     //If any error occurred 
     Log.w("GCMRegIntentService", "Registration error"); 
     registrationComplete = new Intent(REGISTRATION_ERROR); 
    } 

    //Sending the broadcast that registration is completed 
    LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete); 

} 
} 

Und der Zuhörer Service:

public class GCMPushReceiverService extends GcmListenerService { 

private static final String TAG = "GCMPushReceiverService"; 

//with every new message 
@Override 
public void onMessageReceived(String from, Bundle data){ 
    System.out.println("WE'VE RECIEVED A MESSAGE"); 
    String message = data.getString("message"); 
    Log.d(TAG, "From: " + from); 
    Log.d(TAG, "Message: " + message); 
    sendNotification(message); 
} 

private void sendNotification(String message) { 
    Intent intent = new Intent(this, LogInPage.class); 
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
    int requestCode = 0; 
    PendingIntent pendingIntent = 
      PendingIntent.getActivity(this, requestCode, intent, PendingIntent.FLAG_ONE_SHOT); 
    Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); 
    NotificationCompat.Builder noBuilder = new NotificationCompat.Builder(this); 
    noBuilder.setContentTitle("title"); 
    noBuilder.setContentText(message); 
    noBuilder.setContentIntent(pendingIntent); 
    noBuilder.setSound(sound); 
    NotificationManager notificationManager = 
      (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 
    notificationManager.notify(0, noBuilder.build()); //0 = ID of notification 
} 
} 

Schließlich ist, wie es von einem gewissen Nutzen sein können, die Informationen Transporter/networking Klasse:

public class Transporter { 
private String subject; 
private String request; 
private String key; 
private Date lastUpdateDate; 
private boolean forceLoad = false; 
private Date requestDate; 
private Date responseDate; 
private int status; 
private String statusMsg = ""; 
private String tempKey = ""; 

private JSONObject additionalInfo = null; 
private JSONObject parameters; 

public static String sessionGUID = ""; 
public static String userGUID = ""; 

public static String SERVER = Constants.qa_api; 

//transporter object to interact with the server, containing information about the request 
//made by the user 
public Transporter(String pSubject, String pRequest, String pKey, 
           JSONObject parms, String userGUID, String sessionGUID) 
{ 
    subject = pSubject; 
    request = pRequest; 
    key = pKey; 
    parameters = parms; 
    setUserGUID(userGUID); 
    setSessionGUID(sessionGUID); 
} 

//implements an API call for a given transporter, takes 2 arguments: 
//the application context (call getApplicationContext() whenever it's called) 
//and a String that represents the field that we are trying to update (if there is one) 
//i.e. if we are calling getUserFromSession(), we want the user guid so jsonID = "userGUID" 
public void makeAPICall(final Context context, final String jsonID) { 

    RequestQueue mRequestQueue = 
      RequestQueueSingleton.getInstance(context).getRequestQueue(); 
    String targetURL = getServerURL() + "/Transporter.aspx"; 

    StringRequest postRequest = new StringRequest(Request.Method.POST, targetURL, 
      new Response.Listener<String>() { 
       @Override 
       public void onResponse(String response) { 
        String parseXML= parseXML(response); 
        System.out.println("response: " + parseXML); 

        JSONObject lastResponseContent = null; 
        try { 
         lastResponseContent = new JSONObject(parseXML); 
        } catch (JSONException e) { 
         e.printStackTrace(); 
        } 
        try { 
         if (lastResponseContent != null && !jsonID.equals("")) { 
          String info = lastResponseContent.getString(jsonID); 
          if (jsonID.equals("userGUID")) { 
           userGUID = info; 
           RequestQueueSingleton.getInstance(context).setUserGUID(userGUID); 
          } 
         } 
         //put other things in here to pull whatever info 
        } catch (JSONException e) { 
         e.printStackTrace(); 
        } 
       } 
      }, new Response.ErrorListener() { 
     @Override 
     public void onErrorResponse(VolleyError error) { 
      error.printStackTrace(); 
     } 
    }) { 
     @Override 
     public byte[] getBody() throws AuthFailureError { 
      String body = getXML(subject, 
        request, "", 
        sessionGUID, userGUID, null, parameters); 
      return body.getBytes(); 
     } 
    }; 
    postRequest.setTag("POST"); 
    mRequestQueue.add(postRequest); 
} 

Antwort

0

Die Calls von Volley sind also nicht sequentiell, so dass der erste Aufruf (um eine userGUID zu erhalten) nicht vor dem zweiten Aufruf zurückkam (um sich für Benachrichtigungen zu registrieren), also während die Token-Registrierung "erfolgreich" war, gab es keinen entsprechenden Benutzer Informationen, so wusste es nicht, wie/wohin die Push-Benachrichtigung zu senden. Um dies zu lösen, habe ich einen speziellen Fall in der makeAPICall-Klasse gemacht, die eine andere StringRequest erstellt hat, die zuerst die normale getUserFromSession, dann aber rekursiv MakeAPICall mit der neuen userGUID-Information aufgerufen hat. Um eine Endlosschleife zu vermeiden, habe ich eine if else-Anweisung verwendet: (wenn userGUID == null || userGUID.equals ("")), dann habe ich den rekursiven Aufruf ausgeführt. Wenn der erste Aufruf zurückgegeben wurde, war diese Bedingung immer falsch und würde dies auch tun mache nur einen rekursiven Aufruf. Diese Antwort mag ein bisschen weitschweifig sein, aber der Schlüssel zum Mitnehmen ist onResponse, um einen weiteren Volley-Aufruf für sequentielle Anfragen zu machen. Siehe: Volley - serial requests instead of parallel? und Does Volley library handles all the request sequentially

+0

Hi Ethan. Sie sollten weitermachen und dies als die richtige Antwort akzeptieren. Es ist nichts falsch mit [Beantworten Sie Ihre eigene Frage] (http://stackoverflow.com/help/self-answer). –

+1

^es gibt eine minimale Zeit, um Ihre eigene Antwort zu akzeptieren (entweder im Allgemeinen oder weil ich ein neuer Benutzer bin) - es lässt mich nicht für weitere 6 Stunden akzeptieren – Ethan

0

Sie einen Beitrag senden müssen die URL "https://android.googleapis.com/gcm/send":

private void sendGCM() { 

    StringRequest strReq = new StringRequest(Request.Method.POST, 
      "https://android.googleapis.com/gcm/send", new Response.Listener<String>() { 

     @Override 
     public void onResponse(String response) { 

     } 
    }, new Response.ErrorListener() { 

     @Override 
     public void onErrorResponse(VolleyError error) { 
      NetworkResponse networkResponse = error.networkResponse; 
      Log.e(TAG, "Volley error: " + error.getMessage() + ", code: " + networkResponse); 
      Toast.makeText(getApplicationContext(), "Volley error: " + error.getMessage(), Toast.LENGTH_SHORT).show(); 
     } 
    }) { 

     @Override 
     protected Map<String, String> getParams() { 
      Map<String, String> params = new HashMap<>(); 
      params.put("data", "message that you send"); 
      params.put("to", "token gcm"); 

      Log.e(TAG, "params: " + params.toString()); 
      return params; 
     } 

     @Override 
     public Map<String, String> getHeaders() throws AuthFailureError { 
      Map<String,String> headers = new HashMap<String, String>(); 
      headers.put("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); 
      headers.put("Authorization", "key="google key"); 
      return headers; 
     } 

    }; 
} 
+0

An welchem ​​Punkt? Ich sende die Benachrichtigungen mit einer Web-API, weshalb ich keinen Code zum Posten von Benachrichtigungen hinzugefügt habe - mein Problem ist mit dem Empfang der Downstream-Nachrichten – Ethan

+0

Sie setzen alle Berechtigungen in das Manifest? –

+0

yeah-- siehe meine Bearbeitung oben und antworte unten. Das Problem war die Abfolge (oder das Fehlen davon) der Volley-Anfragen, die zur Registrierung des Geräts ohne einen assoziierten Benutzer führten, so dass die benutzerbezogenen Nachrichten von GCM nicht auf dem Gerät eintrafen. Vielen Dank für Ihre Hilfe/Zeit sowieso – Ethan

Verwandte Themen