1

編集:それを考え出した - 私は、サーバーに保存し、登録トークンを生成しようとした後、プッシュ通知を送信するためにトークンを使用していますGCM通知受信/トークン登録

以下の回答を参照してください。この時点で、登録トークンを正常に送信して保存し、Web APIから通知を送信していますが、デバイスに到着していません。 R.string.gcm_defaultSenderId(つまりGCMの送信者キー)を置き換える必要があるかどうか、私は疑問を抱いていました。トークン登録用コードと通知リスナーを含めています。

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); 

} 
} 

そしてリスナー・サービス:あなたがポストを送信する必要が

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); 
} 

答えて

0

したがって、Volleyコールは非シーケンシャルなので、最初のコール(userGUIDを取得する)は2番目のコール(通知用に登録する)の前に戻らなかったため、トークン登録が「成功」している間は、プッシュ通知を送信する方法や場所を知らないようにしました。解決するために、私はmakeAPICallクラスの特別なケースを作成しました。別のStringRequestを作成しました。最初は基本的には通常のgetUserFromSessionを行いましたが、新しいuserGUID情報で再帰的にMakeAPICallを呼び出しました。無限ループを避けるために、if else文を使用しました。(userGUID == null || userGUID.equals( ""))、再帰呼び出しを行ったので、最初の呼び出しが返されたときに条件が常にfalseになりました。 1つの再帰呼び出しのみを行います。この回答はちょっとしたものかもしれませんが、キーを奪うのはonResponseを使って別のVolleyが順次リクエストを行うようにすることです。参照:Volley - serial requests instead of parallel?Does Volley library handles all the request sequentially

+0

こんにちはイーサン。あなたは先に進み、正しい答えとしてこれを受け入れるべきです。 [あなた自身の質問に答える](http://stackoverflow.com/help/self-answer)には何も問題はありません。 –

+1

^あなた自身の回答を受け入れるための最小限の時間があります(一般的に、または私が新しいユーザーであるため) - それはさらに6時間受け入れることはできません – Ethan

0

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 
} 
} 

最後に、それはいくつかの支援、情報トランスポーター/ネットワーキング・クラスのものとすることができるよう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

どの時点ですか?私はWeb APIを使って通知を送信しています。なぜなら、通知を送信するためのコードは含まれていないからです。私の問題は、ダウンストリームメッセージを受信することです。 – Ethan

+0

マニフェストにすべての権限を入れますか? –

+0

ええ、私の上記の編集と下記の回答を参照してください。問題は関連ユーザーのないデバイスの登録につながるVolleyリクエストのシーケンシング(またはその欠如)であったため、GCMのユーザーターゲットメッセージはデバイスに届いていませんでした。とにかくあなたの助け/時間の束をありがとう – Ethan

関連する問題