Mar 03

Google Cloud Messaging uygulamasının Android kısmına geçelim.

Öncelikle yeni bir android projesi oluşturalım. Projenin SDK Manager kısmına gidelim, açılan pencerede Extras sekmesinin altında Google Cloud Messaging Library ‘i kuralım.sdk_manager

Ardından proje dosyasının libs klasörü altına gcm.jar dosyasını eklemeliyiz. Bu jar dosyasını registration id değerini üretirken kullanacağız.

Gcm.jar dosyasını anlatımın sonrasında projenin kod dosyasını paylaşacağım için, oradan erişebilirsiniz.

Bir sonraki adımda uygulamamızı test edeceğimiz sanal cihazın ayarlarına değinelim. Sanal cihazın hedef olarak Google APIs seçilmesi gerekir ki GCM işlemi başarıyla gerçekleştirilsin.

avm_gcm

Ardından projemizin Androidmanifest.xml dosyası içerisine girelim. Gerekli izinleri tanımlayalım.

INTERNET : Uygulama içerisinde internet kullanımına izin verir.

ACCESS_NETWORK_STATE : Network durumuna erişmek için gerekli izindir.

GET_ACCOUNTS : GCM için gerekli olan Google Accounts iznidir

WAKE_LOCK : Uygulamanın uyku vaziyette iken uyanması gerekirse bu izin gereklidir.

VIBRATE : Notification geldiğinde titreşim özelliğine izin verir.

Şimdi AndroidManifest.xml dosyanın tamamını paylaşalım.

Burada belirtmem gerekir ki benim oluşturduğum android uygulamasının proje adı : “com.project.gcmproject”

AndroidManifest.xml




    

    
    
    
    
    
    
    
        
       
       
          
    
    
    
        
            
                

                
            
        
        
        
         
            

                
                
                
                

                
            
        
        
        
    

Şimdi res–>values klasörü altındaki string.xml dosyasının içindekileri paylaşalım.

String.xml




    GCMProject
    Settings
    Hello world!
    Settings
    Android Push Notifications
    Please set the %1$s constant and recompile the app.
    Device is already registered on server.
    GCM: device successfully registered!
    GCM: device successfully unregistered!
    GCM: you got message!
    GCM: error (%1$s).
    GCM: recoverable error (%1$s).
    GCM: server deleted %1$d pending messages!
    Trying (attempt %1$d/%2$d) to register device on Demo Server.
    Demo Server: successfully added device!
    Demo Server: successfully removed device!
    Could not register device on Demo Server after %1$d attempts.
    Could not unregister device on Demo Server (%1$s).
    Register
    Unregister
    Clear
    Exit

Bilindiği üzere string.xml ile hem ekranda görüntülenecek string değerleri burada oluşturarak aynı string değerini defalarca kullanabiliyoruz, hem de aynı projeyi farklı dillerde oluşturacak isek işimizi kolaylaştırıyoruz.

GCMIntentService.java

package com.project.gcmproject;


import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import com.google.android.gcm.GCMBaseIntentService;

public class GCMIntentService extends GCMBaseIntentService {

	private static final String TAG = "GCMIntentService";
		
	private Controller aController = null;
    public GCMIntentService() {
    	// Call extended class Constructor GCMBaseIntentService
    	super(Config.GOOGLE_SENDER_ID);
    	
    } 

    /**
     * Method called on device registered
     **/
    @Override
    protected void onRegistered(Context context, String registrationId) {
    	
    	//Get Global Controller Class object (see application tag in AndroidManifest.xml)
    	if(aController == null)
           aController = (Controller) getApplicationContext();
    	
        Log.i(TAG, "Device registered: regId = " + registrationId);
        aController.displayMessageOnScreen(context, "Your device registred with GCM");
        Log.d("NAME", "ad");
       // aController.register(context, "ad", "mail", registrationId);
    }

    /**
     * Method called on device unregistred
     * */
    @Override
    protected void onUnregistered(Context context, String registrationId) {
    	if(aController == null)
            aController = (Controller) getApplicationContext();
        Log.i(TAG, "Device unregistered");
        aController.displayMessageOnScreen(context, getString(R.string.gcm_unregistered));
        aController.unregister(context, registrationId);
    }

    /**
     * Method called on Receiving a new message from GCM server
     * */
    @Override
    protected void onMessage(Context context, Intent intent) {
    	
    	if(aController == null)
            aController = (Controller) getApplicationContext();
    	
        Log.i(TAG, "Received message");
        String message = intent.getExtras().getString("price");
      aController.displayMessageOnScreen(context, message);
      generateNotification(context, message);
    } 
    

    /**
     * Method called on receiving a deleted message
     * */

    @Override
    protected void onDeletedMessages(Context context, int total) {
    	
    	if(aController == null)
            aController = (Controller) getApplicationContext();
    	
        Log.i(TAG, "Received deleted messages notification");
        String message = getString(R.string.gcm_deleted, total);
        aController.displayMessageOnScreen(context, message);
        // notifies user
        generateNotification(context, message);
    }

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

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

    
    
    /**
     * Create 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);
        notificationIntent.putExtra("message", message);
        // 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.defaults |= Notification.DEFAULT_LIGHTS;
          
        // Vibrate if vibrate is enabled
        notification.defaults |= Notification.DEFAULT_VIBRATE;
        notificationManager.notify(0, notification);   
        
    } 

}

İçerisindeki onRegistered metodu kayıt işlemi için, onMessage metodu uygulamaya notification mesajı geldiğinde, generateNotification metodu gelen mesajı bildirim şeklinde göstermek için kullanılan metotlardır.

Controller.java

package com.project.gcmproject;

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Map.Entry;

import com.google.android.gcm.GCMRegistrar; 

import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.util.Log;

public class Controller extends Application{
	
	private  final int MAX_ATTEMPTS = 5;
    private  final int BACKOFF_MILLI_SECONDS = 2000;
    private  final Random random = new Random();
	
    
	 // Register this account with the server.
    public void register(final Context context, String name, String mail, String regId) {
    	 
        Log.i(Config.TAG, "registering device (regId = " + regId + ")");
        
        String serverUrl = Config.YOUR_SERVER_URL;
        
        Map params = new HashMap();
        params.put("regId", regId);
        params.put("name", name);
        params.put("mail", mail);
        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(Config.TAG, "Attempt #" + i + " to register");
            
            try {
            	//Send Broadcast to Show message on screen
            	displayMessageOnScreen(context, context.getString(
                        R.string.server_registering, i, MAX_ATTEMPTS));
                
                // Post registration values to web server
                post(serverUrl, params);
                
                GCMRegistrar.setRegisteredOnServer(context, true);
                
                //Send Broadcast to Show message on screen
                String message = context.getString(R.string.server_registered);
                displayMessageOnScreen(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(Config.TAG, "Failed to register on attempt " + i + ":" + e);
                
                if (i == MAX_ATTEMPTS) {
                    break;
                }
                try {
                	
                    Log.d(Config.TAG, "Sleeping for " + backoff + " ms before retry");
                    Thread.sleep(backoff);
                    
                } catch (InterruptedException e1) {
                    // Activity finished before we complete - exit.
                    Log.d(Config.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);
        
        //Send Broadcast to Show message on screen
        displayMessageOnScreen(context, message);
    }

     // Unregister this account/device pair within the server.
     void unregister(final Context context, final String regId) {
    	 
        Log.i(Config.TAG, "unregistering device (regId = " + regId + ")");
        
        String serverUrl = Config.YOUR_SERVER_URL + "/unregister";
        Map params = new HashMap();
        params.put("regId", regId);
        
        try {
            post(serverUrl, params);
            GCMRegistrar.setRegisteredOnServer(context, false);
            String message = context.getString(R.string.server_unregistered);
            displayMessageOnScreen(context, message);
        } catch (IOException e) {
        	
            // At this point the device is unregistered from GCM, but still
            // registered in the our 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());
            displayMessageOnScreen(context, message);
        }
    }

    // Issue a POST request to the server.
    private static void post(String endpoint, Map params)
            throws IOException {   	
        
        URL url;
        try {
        	
            url = new URL(endpoint);
            
        } catch (MalformedURLException e) {
            throw new IllegalArgumentException("invalid url: " + endpoint);
        }
        
        StringBuilder bodyBuilder = new StringBuilder();
        Iterator> iterator = params.entrySet().iterator();
        
        // constructs the POST body using the parameters
        while (iterator.hasNext()) {
            Entry param = iterator.next();
            bodyBuilder.append(param.getKey()).append('=')
                    .append(param.getValue());
            if (iterator.hasNext()) {
                bodyBuilder.append('&');
            } 
        }  
         
        String body = bodyBuilder.toString();
        
        Log.v(Config.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 response is not success
            if (status != 200) {
            	
              throw new IOException("Post failed with error code " + status);
            }
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
      }
    

   // Notifies UI to display a message.
   void displayMessageOnScreen(Context context, String message) {
    	 
        Intent intent = new Intent(Config.DISPLAY_MESSAGE_ACTION);
        intent.putExtra(Config.EXTRA_MESSAGE, message);
      //  sentmessage.text.setText(message);
        // Send Broadcast to Broadcast receiver with message
        context.sendBroadcast(intent);
   
        
    }
    
        
    private PowerManager.WakeLock wakeLock;
    
    public  void acquireWakeLock(Context context) {
        if (wakeLock != null) wakeLock.release();

        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        
        wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
                PowerManager.ACQUIRE_CAUSES_WAKEUP |
                PowerManager.ON_AFTER_RELEASE, "WakeLock");
        
        wakeLock.acquire();
    }

    public  void releaseWakeLock() {
        if (wakeLock != null) wakeLock.release(); wakeLock = null;
    }
   
}

Controller.java, GCMIntentService.java ile birlikte kullanıyoruz. Bu dosya GCM registration id üretmek için gerekli metotları içermektedir.

Config.java

package com.project.gcmproject;

public interface Config {
	

	static final String YOUR_SERVER_URL =  "http://huseyinbodur.net/huseyinHtml/messageApp/gcm_server_files/old/register.php";
	// register.php dosyasına giderek kayıt yapıyoruz.

    static final String GOOGLE_SENDER_ID = "801935290811";  // Google proje id si burada.
    /**
     * Tag used on log messages.
     */
    static final String TAG = "GCM Example";

    static final String DISPLAY_MESSAGE_ACTION =
            "com.project.gcmproject.DISPLAY_MESSAGE";
    
    static final String EXTRA_MESSAGE = "message";

Bu dosyanın içerisinde gerekli ayarları yapıyoruz. Diğer sınıflardan bu sınıfın değişkenlerini çağırıyoruz. Bu nedenle ilerde uygulama için herhangi bir yapılandırma ayarı yapmamız gerektiğinde, değişikliklerimizi sadece bu sınıf içerisinde yapıyoruz.

activity_main.xml



    

    

        
    

    

    

    

Activity_main.xml, kullanıcı adı ve mail adresinin alındığı ve sisteme register edildiği sayfasının xml tasarım yapısıdır.

MainActivity.java

package com.project.gcmproject;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import com.google.android.gcm.GCMRegistrar;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {

	Button kaydet;
	EditText ad,mail;
	String regIdim;
	Controller eController;
	public static HttpPost httppost;
	public static StringBuffer buffer;
	public static HttpResponse response;
	public static HttpClient httpclient;
	public static List nameValuePairs;   
	public static boolean parsingComplete = true;	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		kaydet=(Button)findViewById(R.id.button1);
		ad=(EditText)findViewById(R.id.editText1);
		mail=(EditText)findViewById(R.id.editText2);
  //		aController = (Controller) getApplicationContext();
		eController = (Controller) getApplicationContext();
  		GCMRegistrar.onDestroy(this);
      	// Make sure the device has the proper dependencies.
    	GCMRegistrar.checkDevice(this);

    	// Make sure the manifest permissions was properly set 
    	GCMRegistrar.checkManifest(this);
    	//GCMRegistrar.setRegisteredOnServer(this, true);
    		
    	regIdim = GCMRegistrar.getRegistrationId(this);
    		if (regIdim.equals("") || regIdim.trim().length()==0) {
    			  GCMRegistrar.register(this, "801935290811");
    			}

      		// Register custom Broadcast receiver to show messages on activity
    		registerReceiver(mHandleMessageReceiver, new IntentFilter(
    				Config.DISPLAY_MESSAGE_ACTION));
      		
		kaydet.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
			if(ad.getText().toString().trim().length()==0 || mail.getText().toString().trim().length()==0)
				Toast.makeText(getApplicationContext(),"Lütfen Tüm Alanları Doldurun.", Toast.LENGTH_LONG).show();	
			else
				try{
					new registerAsnk().execute(Config.YOUR_SERVER_URL);				
				     } catch(Exception e) {}
			
				
			}
		});
		
	}

	private class registerAsnk extends AsyncTask {
        @Override
        protected String doInBackground(String... urls) {
        
         return register(urls[0], ad.getText().toString(),mail.getText().toString(),regIdim);
                     
        } 
        
        @Override
        protected void onPostExecute(String result) {
        	ad.setText("");mail.setText("");
        	Toast.makeText(getApplicationContext(), "Kaydınız Gerçekleştirildi.", Toast.LENGTH_LONG).show();
        	
        }
    }
	
	
	public static String register(String url,String name,String mail,String regId)
	 {
		 String responseValue="";
		 try{
		 httpclient=new DefaultHttpClient();
			httppost= new HttpPost(url);

			nameValuePairs = new ArrayList(2);
			nameValuePairs.add(new BasicNameValuePair("name",name)); 
			nameValuePairs.add(new BasicNameValuePair("email",mail)); 
			nameValuePairs.add(new BasicNameValuePair("regId",regId)); 
			httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs,"UTF-8"));
			
			response=httpclient.execute(httppost);
			ResponseHandler responseHandler = new BasicResponseHandler();
			responseValue = httpclient.execute(httppost, responseHandler);
		
		 }catch(Exception e){
				Log.e("Exception : " , e.getMessage());}
			
		 
		 return responseValue;
	 }
	

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
    // Create a broadcast receiver to get message and show on screen 
		private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() {
			
			@Override
			public void onReceive(Context context, Intent intent) {
				
				eController.acquireWakeLock(getApplicationContext());
				eController.releaseWakeLock();

			}
		};
		
}

Bu dosya içerisinde kullanıcıdan ad ve mail bilgilerini alıp, GCM registration id ’si ile birlikte sisteme kaydediyoruz.

Tüm yapmamız gereken bunlar. Bu aşamadan sonra projeyi çalıştırıp push notification örneği yapalım.
Önce uygulama içerisinden örnek bir kayıt işlemi gerçekleştirelim.

deneme_phone
Web sayfasından gelen kaydı kontrol edebiliriz.
index_push_gcm

Gcm_users tablosu
gcm_sunucu

Örnek bir push işlemi gerçekleştirelim.
deneme_push
Send Push Notification butonuna bastığımızda ekranımıza push notification mesajın düştüğünü görürüz.
deneme_phone2

Çalışmamız burada tamamlanmıştır. Örnek Java dosyasını bu linkten indirebilirsiniz.
Eğer örnek dosya çalışmaz ise console.google ’da oluşturduğum api’yi kaldırmış olabilirim. Bu nedenle daha önceki yazılarda da yazdığım şekilde kendi apinizi oluşturmanız konuyu kavramanız için daha faydalı olacaktır.

Yorum Yaz