2014-02-16 128 views
0

我正在從本教程的谷歌雲消息的推送通知應用程序: here 這是我見過的最好的教程。 它工作正常,但我無法將其實施到我自己的項目中。 似乎從GCMIntentService發生問題。此服務在GCMRegistrar.register(this, SENDER_ID);後自動運行在應用程序中,但我不知道如何?! 並且沒有運行此服務的位置。推送通知與GCM問題

所以我不知道是否有人可以解釋我如何實現這一點到我的應用程序,並解釋一些有線部分的工作原理。謝謝。

活動要與谷歌進行註冊:爲寄存器

public class MainActivity extends Activity { 
    // label to display gcm messages 
    TextView lblMessage; 

    // Asyntask 
    AsyncTask<Void, Void, Void> mRegisterTask; 

    // Alert dialog manager 
    AlertDialogManager alert = new AlertDialogManager(); 

    // Connection detector 
    ConnectionDetector cd; 

    public static String name; 
    public static String email; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     cd = new ConnectionDetector(getApplicationContext()); 

     // Check if Internet present 
     if (!cd.isConnectingToInternet()) { 
      // Internet Connection is not present 
      alert.showAlertDialog(MainActivity.this, 
        "Internet Connection Error", 
        "Please connect to working Internet connection", false); 
      // stop executing code by return 
      return; 
     } 

     // Getting name, email from intent 
     Intent i = getIntent(); 

     name = i.getStringExtra("name"); 
     email = i.getStringExtra("email");  

     // Make sure the device has the proper dependencies. 
     GCMRegistrar.checkDevice(this); 

     // Make sure the manifest was properly set - comment out this line 
     // while developing the app, then uncomment it when it's ready. 
     GCMRegistrar.checkManifest(this); 

     lblMessage = (TextView) findViewById(R.id.lblMessage); 

     registerReceiver(mHandleMessageReceiver, new IntentFilter(
       DISPLAY_MESSAGE_ACTION)); 

     // Get GCM registration id 
     final String regId = GCMRegistrar.getRegistrationId(this); 

     Log.i("LOG", "register ID is:"+regId); 
     // Check if regid already presents 
     if (regId.equals("")) { 
      // Registration is not present, register now with GCM 
      Log.i("LOG", "p1"); 
      GCMRegistrar.register(this, SENDER_ID); 
     } else { 

      // Device is already registered on GCM 
      if (GCMRegistrar.isRegisteredOnServer(this)) { 
       Log.i("LOG", "p2"); 
       // Skips registration.   
       //GCMRegistrar.unregister(this); 
       Toast.makeText(getApplicationContext(), "Already registered with GCM", Toast.LENGTH_LONG).show(); 
      } else { 
       Log.i("LOG", "p3"); 
       // Try to register again, but not in the UI thread. 
       // It's also necessary to cancel the thread onDestroy(), 
       // hence the use of AsyncTask instead of a raw thread. 
       final Context context = this; 
       mRegisterTask = new AsyncTask<Void, Void, Void>() { 

        @Override 
        protected Void doInBackground(Void... params) { 
         // Register on our server 
         // On server creates a new user 
         ServerUtilities.register(context, name, email, regId); 

         return null; 
        } 

        @Override 
        protected void onPostExecute(Void result) { 
         mRegisterTask = null; 
        } 

       }; 
       Log.i("LOG", "pre execute"); 
       mRegisterTask.execute(null, null, null); 
      } 
     } 
    }  

    /** 
    * Receiving push messages 
    * */ 
    private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
      String newMessage = intent.getExtras().getString(EXTRA_MESSAGE); 
      // Waking up mobile if it is sleeping 
      WakeLocker.acquire(getApplicationContext()); 

      /** 
      * Take appropriate action on this message 
      * depending upon your app requirement 
      * For now i am just displaying it on the screen 
      * */ 

      // Showing received message 
      lblMessage.append(newMessage + "\n");   
      Toast.makeText(getApplicationContext(), "New Message: " + newMessage, Toast.LENGTH_LONG).show(); 

      // Releasing wake lock 
      WakeLocker.release(); 
     } 
    }; 

    @Override 
    protected void onDestroy() { 
     if (mRegisterTask != null) { 
      mRegisterTask.cancel(true); 
     } 
     try { 
      unregisterReceiver(mHandleMessageReceiver); 
      GCMRegistrar.onDestroy(this); 
     } catch (Exception e) { 
      Log.e("UnRegister Receiver Error", "> " + e.getMessage()); 
     } 
     super.onDestroy(); 
    } 

} 

活動:

public final class ServerUtilities { 
    private static final int MAX_ATTEMPTS = 5; 
    private static final int BACKOFF_MILLI_SECONDS = 2000; 
    private static final Random random = new Random(); 

    /** 
    * Register this account/device pair within the server. 
    * 
    */ 
    static void register(final Context context, String name, String email, final String regId) { 

     Log.i("LOG", "reg p1"); 
     Log.i(TAG, "registering device (regId = " + regId + ")"); 
     String serverUrl = SERVER_URL; 
     Map<String, String> params = new HashMap<String, String>(); 
     params.put("regId", regId); 
     params.put("name", name); 
     params.put("email", email); 

     long backoff = BACKOFF_MILLI_SECONDS + random.nextInt(1000); 
     // Once GCM returns a registration id, we need to register on our server 
     // As the server might be down, we will retry it a couple 
     // times. 
     for (int i = 1; i <= MAX_ATTEMPTS; i++) { 
      Log.d(TAG, "Attempt #" + i + " to register"); 
      try { 
       displayMessage(context, context.getString(
         R.string.server_registering, i, MAX_ATTEMPTS)); 
       post(serverUrl, params); 
       GCMRegistrar.setRegisteredOnServer(context, true); 
       String message = context.getString(R.string.server_registered); 
       CommonUtilities.displayMessage(context, message); 
       return; 
      } catch (IOException e) { 
       // Here we are simplifying and retrying on any error; in a real 
       // application, it should retry only on unrecoverable errors 
       // (like HTTP error code 503). 
       Log.e(TAG, "Failed to register on attempt " + i + ":" + e); 
       if (i == MAX_ATTEMPTS) { 
        break; 
       } 
       try { 
        Log.d(TAG, "Sleeping for " + backoff + " ms before retry"); 
        Thread.sleep(backoff); 
       } catch (InterruptedException e1) { 
        // Activity finished before we complete - exit. 
        Log.d(TAG, "Thread interrupted: abort remaining retries!"); 
        Thread.currentThread().interrupt(); 
        return; 
       } 
       // increase backoff exponentially 
       backoff *= 2; 
      } 
     } 
     String message = context.getString(R.string.server_register_error, 
       MAX_ATTEMPTS); 
     CommonUtilities.displayMessage(context, message); 
    } 

    /** 
    * Unregister this account/device pair within the server. 
    */ 
    static void unregister(final Context context, final String regId) { 
     Log.i(TAG, "unregistering device (regId = " + regId + ")"); 
     String serverUrl = SERVER_URL + "/unregister"; 
     Map<String, String> params = new HashMap<String, String>(); 
     params.put("regId", regId); 
     try { 
      post(serverUrl, params); 
      GCMRegistrar.setRegisteredOnServer(context, false); 
      String message = context.getString(R.string.server_unregistered); 
      CommonUtilities.displayMessage(context, message); 
     } catch (IOException e) { 
      // At this point the device is unregistered from GCM, but still 
      // registered in the server. 
      // We could try to unregister again, but it is not necessary: 
      // if the server tries to send a message to the device, it will get 
      // a "NotRegistered" error message and should unregister the device. 
      String message = context.getString(R.string.server_unregister_error, 
        e.getMessage()); 
      CommonUtilities.displayMessage(context, message); 
     } 
    } 

    /** 
    * Issue a POST request to the server. 
    * 
    * @param endpoint POST address. 
    * @param params request parameters. 
    * 
    * @throws IOException propagated from POST. 
    */ 
    private static void post(String endpoint, Map<String, String> params) 
      throws IOException {  

     URL url; 
     try { 
      url = new URL(endpoint); 
     } catch (MalformedURLException e) { 
      throw new IllegalArgumentException("invalid url: " + endpoint); 
     } 
     StringBuilder bodyBuilder = new StringBuilder(); 
     Iterator<Entry<String, String>> iterator = params.entrySet().iterator(); 
     // constructs the POST body using the parameters 
     while (iterator.hasNext()) { 
      Entry<String, String> param = iterator.next(); 
      bodyBuilder.append(param.getKey()).append('=') 
        .append(param.getValue()); 
      if (iterator.hasNext()) { 
       bodyBuilder.append('&'); 
      } 
     } 
     String body = bodyBuilder.toString(); 
     Log.v(TAG, "Posting '" + body + "' to " + url); 
     byte[] bytes = body.getBytes(); 
     HttpURLConnection conn = null; 
     try { 
      Log.e("URL", "> " + url); 
      conn = (HttpURLConnection) url.openConnection(); 
      conn.setDoOutput(true); 
      conn.setUseCaches(false); 
      conn.setFixedLengthStreamingMode(bytes.length); 
      conn.setRequestMethod("POST"); 
      conn.setRequestProperty("Content-Type", 
        "application/x-www-form-urlencoded;charset=UTF-8"); 
      // post the request 
      OutputStream out = conn.getOutputStream(); 
      out.write(bytes); 
      out.close(); 
      // handle the response 
      int status = conn.getResponseCode(); 
      if (status != 200) { 
       throw new IOException("Post failed with error code " + status); 
      } 
     } finally { 
      if (conn != null) { 
       conn.disconnect(); 
      } 
     } 
     } 
} 

,這是服務:

public class GCMIntentService extends GCMBaseIntentService { 

    private static final String TAG = "GCMIntentService"; 

    @Override 
    public void onCreate() { 

     Log.i("LOG", "service created"); 
    }; 
    public GCMIntentService() { 
     super(SENDER_ID); 
    } 

    /** 
    * Method called on device registered 
    **/ 
    @Override 
    protected void onRegistered(Context context, String registrationId) { 
     Log.i("LOG", "register service p1"); 
     Log.i(TAG, "Device registered: regId = " + registrationId); 
     displayMessage(context, "Your device registred with GCM"); 
     Log.d("NAME", MainActivity.name); 
     ServerUtilities.register(context, MainActivity.name, MainActivity.email, registrationId); 
    } 

    /** 
    * Method called on device un registred 
    * */ 
    @Override 
    protected void onUnregistered(Context context, String registrationId) { 
     Log.i(TAG, "Device unregistered"); 
     Log.i("LOG", "Unregister service p1"); 
     displayMessage(context, getString(R.string.gcm_unregistered)); 
     ServerUtilities.unregister(context, registrationId); 
    } 

    /** 
    * Method called on Receiving a new message 
    * */ 
    @Override 
    protected void onMessage(Context context, Intent intent) { 
     Log.i(TAG, "Received message"); 
     String message = intent.getExtras().getString("price"); 

     displayMessage(context, message); 
     // notifies user 
     generateNotification(context, message); 
    } 

    /** 
    * Method called on receiving a deleted message 
    * */ 
    @Override 
    protected void onDeletedMessages(Context context, int total) { 
     Log.i(TAG, "Received deleted messages notification"); 
     String message = getString(R.string.gcm_deleted, total); 
     displayMessage(context, message); 
     // notifies user 
     generateNotification(context, message); 
    } 

    /** 
    * Method called on Error 
    * */ 
    @Override 
    public void onError(Context context, String errorId) { 
     Log.i(TAG, "Received error: " + errorId); 
     displayMessage(context, getString(R.string.gcm_error, errorId)); 
    } 

    @Override 
    protected boolean onRecoverableError(Context context, String errorId) { 
     // log message 
     Log.i(TAG, "Received recoverable error: " + errorId); 
     displayMessage(context, getString(R.string.gcm_recoverable_error, 
       errorId)); 
     return super.onRecoverableError(context, errorId); 
    } 

    /** 
    * Issues a notification to inform the user that server has sent a message. 
    */ 
    private static void generateNotification(Context context, String message) { 
     int icon = R.drawable.ic_launcher; 
     long when = System.currentTimeMillis(); 
     NotificationManager notificationManager = (NotificationManager) 
       context.getSystemService(Context.NOTIFICATION_SERVICE); 
     Notification notification = new Notification(icon, message, when); 

     String title = context.getString(R.string.app_name); 

     Intent notificationIntent = new Intent(context, MainActivity.class); 
     // set intent so it does not start a new activity 
     notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | 
       Intent.FLAG_ACTIVITY_SINGLE_TOP); 
     PendingIntent intent = 
       PendingIntent.getActivity(context, 0, notificationIntent, 0); 
     notification.setLatestEventInfo(context, title, message, intent); 
     notification.flags |= Notification.FLAG_AUTO_CANCEL; 

     // Play default notification sound 
     notification.defaults |= Notification.DEFAULT_SOUND; 

     //notification.sound = Uri.parse("android.resource://" + context.getPackageName() + "your_sound_file_name.mp3"); 

     // Vibrate if vibrate is enabled 
     notification.defaults |= Notification.DEFAULT_VIBRATE; 
     notificationManager.notify(0, notification);  

    } 

} 

回答

0

您使用的是舊教程它使用一個過時的類(GCMRegistrar)。向GCM註冊的推薦方法是類的register方法,它是Google Play服務庫的一部分。這種方法是同步的,應該在後臺運行(不在主線程中)。

這與過時的GCMRegister.register方法不同,它是異步的(Google返回意向服務onRegistered方法中的響應)。

您應該參考offical guideofficial demo中的代碼示例。

+0

好的,有沒有這個新的教程? – Kenji

+0

@Kenji是的。我在我的答案中包含鏈接 – Eran