Android C2DM Nedir? | Android ile C2DM Uygulama Örneği

tarih11.09.2012 13:45 — Programlama, Android,



C2DM nedir?

Google’un Android uygulamaları için geliştirdiği bir mesajlaşma sistemidir. Açılımı: Cloud to Device Messaging. Push Notification olarak da bilinen bu tip mesaj gönderme teknolojilerine Blackberry ve iPhone’dan da aşinayız. Android de 2.2 froyo sürümü ile bu kervana katılmış oldu. Google bu teknolojiyi, gmail ve kontak senkronizasyonu için uzun zamandır zaten kullanıyordu, 2.2 ile birlikte yaptıkları şey teknolojiyi developerlara açmak olmuş.

Android gibi yetenekli bir cihaz ile C2DM kullanarak yapılabilecekler hayal gücüyle sınırlı. Mesela Google Play Store üzerinden seçtiğimiz bir uygulamayı C2DM ile anında telefona kurulmasını sağlayabiliyoruz. Bir chrome extension‘ı sayesinde pc’de gezinirken beğendiğimiz bir sitenin anında cihazda da açılmasını sağlayabiliyoruz.

 

 

C2DM ne işe yarar?

C2DM 1024 karakterlik mesaj göndermeyle sınırlı ancak mesajımızı telefona ilettikten sonra yapılabilecekler Android platformunun yeteneklerine kalıyor. Bir senkronizasyon işlemi başlatabilir, mesajın içinde gönderilecek bir video linkini anında oynatmaya başlayabilir, istediğiniz bir programı (telefon görüşmesi, sms gönderme dahil) başlatabilir, telefonunuzdaki herhangi bir ayarı değiştirebilir, lokasyon servisine erişebilir ve şu an aklıma gelmeyen bir çok şey daha yapabilirsiniz

Android’te zaten sorunsuz olarak background servisleri yazabiliyorduk, periyodik olarak bir sunucuya bağlanıp data çekme imkanımız vardı hatta Android’in socket programming için de bir kısıtlaması bulunmuyor. Peki o zaman neden C2DM’e ihtiyaç duyayım diyor olabilirsiniz. C2DM’in en önemli özelliği cihaz performansını, pil süresini kısaca kullanıcı deneyimini arttırması denebilir: C2DM sayesinde kullanıcıların pil sorununu biraz azalacak gibi görünüyor. Mesela aynı anda 5 uygulama background servis olarak sürekli data çekiyor ya da port dinliyor durumda olursa kaynaklar verimsiz kullanılacak ve pil tüketimi artacaktır. Oysa C2DM ile sadece bir sistem background servisi tüm push mesajlarını dinliyor ve ilgili uygulamaları ayağa kaldırıyor ve kaynaklar daha verimli kullanılıyor olacak. C2DM ile kullanıcıların istem dışı mesaj almasının da önüne geçilebilecek. Sadece yetki verdiği uygulamalardan mesaj alacak böylece mesajlar yüzünden uygulamayı silmek zorunda kalmayacak.

C2DM kullanımı Bu bölümde servisi nasıl kullanacağımızı anlatmaya çalışacağım, Android’in dökümanlarına bakarak ve yaptığım denemelerle edindiğim bilgi ve tecrübeyi paylaşmaya çalışacağım.

Öncelikle developer olarak, gmail hesabımız ile signup formu dolduruyoruz:

http://code.google.com/android/c2dm/signup.html

sonra onay maili bekliyoruz. C2DM kullanımında üç adet ortam kendi aralarında haberleşiyor durumdadır. Bunlardan birisi Android işletim sistemli cihaz, diğeri sizin geliştirdiğiniz bir sunucu yazılımı, üçüncüsü ise Google’ın C2DM sunucusu.

Haberleşme esnasında kullanılan değişkenler:

Sender: Mesaj gönderme için google’ın onay verdiği geliştiricinin email adresi.

Authorization id : Android’e mesaj gönderecek olan sunucunun bu işi yapabilmesi için yetkiye ihtiyacı var. Yoksa önüne gelen sizin google hesabınızla (sender) cihazlara mesaj gönderebilir. Bunun için bir authorization id oluşturmanız lazım.

Registration id: Mesajları alacak olan her Android cihaz için oluşturulan bir id. Bu id’yi kullanarak istediğiniz cihaza mesaj gönderebileceksiniz. Haberleşme dört adımda gerçekleşiyor. Google’dan kendi hesabınız için yetki alma (Authorization) Android uygulaması ilk çalıştığında yapılacak bir registration işlemi Sunucudan cihaza mesaj gönderme Cihazdan mesajı alıp kullanıcıya göstermek.

Her bir adımı nasıl kodlayacağımızdan bahsetmek gerekirse:

Google’dan kendi hesabınız için yetki alma (Authorization) Sender email adresini ve şifresini kullanarak ve bunu bir sefer yapıp bir authorization id oluşturuyoruz. Bu id’yi sunucumuza kaydediyoruz. Sonra mesaj atarken bu id’yi kullanacağız.

 

        HttpClient client = new DefaultHttpClient();
        HttpPost postRequest = new HttpPost("https://www.google.com/accounts/ClientLogin");
        List nameValuePairs = new ArrayList(2); nameValuePairs.add(new BasicNameValuePair("accountType","GOOGLE"));
        nameValuePairs.add(new BasicNameValuePair("Email",senderEmail));
        nameValuePairs.add(new BasicNameValuePair("Passwd","xxxxx"));
        nameValuePairs.add(new BasicNameValuePair("service","ac2dm"));
        nameValuePairs.add(new BasicNameValuePair("source","Uygulama"));

        try {
	        postRequest.setEntity(new UrlEncodedFormEntity(nameValuePairs));
	        postRequest.setHeader("Content-Type", "application/x-www-form-urlencoded");
	        HttpResponse response = client.execute(postRequest);  
	        InputStream inputStream = response.getEntity().getContent();
	        BufferedReader rd = new BufferedReader(new InputStreamReader(inputStream));
	        String line;
	        while ((line = rd.readLine()) != null) {
	        	Log.d(TAG,":"+line);
	        } 
	        client.getConnectionManager().closeExpiredConnections();

        } catch (IOException e) {
        	client.getConnectionManager().closeExpiredConnections();
        	e.printStackTrace();
        }

 

Registration: Android uygulamamız ilk kez çalıştığında registration işlemi yapan bir bölüm kodlamamız gerekiyor. C2DM servera signup olduğunuz gmail hesabınız (buna sender id deniyor) ve application id ile C2DM’e register oluyoruz. C2DM server asenkron olarak bizim uygulamamıza özel bir broadcast yapıyor, bunu receive ediyor ve uygulamamızın üzerinde çalıştığı cihaza özel olan registration id’ye ulaşıyoruz. Son olarak registration id’yi kendi sunucumuza gönderiyor ve orada da saklanmasını sağlıyoruz.

Register işlemini başlattığımız kod code:

   private void register() {
    	Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
    	registrationIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0));
    	registrationIntent.putExtra("sender", emailOfSender); startService(registrationIntent);
    }

    
    //Kullanıcıya unregister hakkı vermek lazım, bunun için:
	private void unregister() {
		Intent unregIntent = new Intent("com.google.android.c2dm.intent.UNREGISTER");
		unregIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0)); startService(unregIntent);
	}

	
    //Google ilettiği registartion id’yi almak için yazdığımız Receiver’ın kodu:
	public class C2DMReceiver extends BroadcastReceiver {
		private static String TAG = "C2DMReceiver";  
		public void onReceive(Context context, Intent intent) {
			if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) {
			handleRegistration(context, intent);
			}
		}
		private void handleRegistration(Context context, Intent intent) {
			String registration = intent.getStringExtra("registration_id");
	
			if (intent.getStringExtra("error") != null) {
				Log.d(TAG, "error: " + intent.getStringExtra("error"));
			} else if (intent.getStringExtra("unregistered") != null) {
				// kendi sunucumuza registration_id'yi sileceğiz...
			} else if (registration != null) {
				// kendi sunucumuza registration_id'yi gonderecegiz...
			}
		}
	}

 

Google periyodik olarak registration id’yi değiştirip broadcast edecek. Bu nedenle receiver periyodik olarak çalışacaktır, önemli olan bu registration id her değiştiğinde kendi serverımıza iletip kayıt altında tutmaktır. Yoksa o kullanıcıya mesajımızı iletemeyiz. Cihaza mesaj gönderme: Geliştireceğimiz server uygulaması daha önce aldığımız ve server tarafta kayıt altında tuttuğumuz authorizationId ve registrationId bilgilerini kullanarak cihaza mesaj gönderebilecektir.

 

    public static String sendMessage(registrationId,authorizationId,data){
    	String retStr ="";
    	try {
    		String registrationId = registrationId; String collapseKey = URLEncoder.encode(data, "UTF-8");
	    	URL url = new URL("https://android.apis.google.com/c2dm/send");
	    	HttpURLConnection connection = (HttpURLConnection) url.openConnection();
	    	connection.setDoOutput(true); connection.setRequestMethod("POST");
	    	connection.setRequestProperty("Authorization", "GoogleLogin auth="+authorizationId);
	    	OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
	    	writer.write("registration_id=" + registrationId); writer.write("&collapse_key=" + collapseKey);
	    	writer.write("&data.SERVER_MESSAGE=" + data); writer.close();  
	    	if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
	    		InputStream is = connection.getInputStream();
	    		byte[] buffer = new byte[1024];
	    		int bytesRead = 0;  
	    		while ((bytesRead = is.read(buffer)) != -1) retStr = retStr + new String(buffer, 0, bytesRead);
	    	} else {
	    		retStr = "error";
	    	}

    	} catch (MalformedURLException e) {
    		e.printStackTrace();
    	} catch (IOException e) {
    		e.printStackTrace();
    	}
    		return retStr;  

    }

 

 

Cihazdan gönderilen mesajı alma: Android tarafında Registration Id’yi alabilmek için yazdığımız receiver’a c2dm mesajını da alabileceğimiz kodları ekliyoruz. CD2DMReceiver class’ının son hali şu şekilde olmalı:

 

    public class C2DMReceiver extends BroadcastReceiver {
        private static String TAG = "C2DMReceiver";
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) {
                handleRegistration(context, intent);
            } else if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
                handleMessage(context, intent);
            }
        }  
    
        private void handleRegistration(Context context, Intent intent) {
            String registration = intent.getStringExtra("registration_id");
            if (intent.getStringExtra("error") != null) {
                Log.d(TAG, "error: " + intent.getStringExtra("error"));
            } else if (intent.getStringExtra("unregistered") != null) {
                // kendi sunucumuzdan registration_id'yi sileceğiz...
            } else if (registration != null) {
                // kendi sunucumuza registration_id'yi gonderecegiz...
            }
        }
    }  

    private void handleMessage(Context context, Intent intent) {
        String message = intent.getExtras().getString("SERVER_MESSAGE");
        Log.d(TAG, "message: " + message);
    }

 

Yazdığımız bu Broadcast recevier’ın sağlıklı çalışabilmesi için manifest dosyasında aşağıdaki permission ve receiver tanımlarının yapılması gerekiyor:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.dinopis.cd2dmtest"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <permission
        android:name="com.example.android.c2dm.simpleclient.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission 
        android:name="com.example.android.c2dm.simpleclient.permission.C2D_MESSAGE" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
            <receiver
            android:name=".C2DMRegistrationReceiver"
            android:permission="com.google.android.c2dm.permission.SEND" >
            <intent-filter >
                <action android:name="com.google.android.c2dm.intent.REGISTRATION" >
                </action>
                <category android:name="com.example.android.c2dm.simpleclient" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

 

Bilgi amaçlı şu sayfadan alıntı yapılmıştır. Kodlar test edilmemiştir.

Konuyla ilgili sayfalar;

Örnek bir video

 




Bir önceki konu başlığımıza göz atmak isterseniz tıklayınız : Android Eclipse - Failed to load properties file for project




    Yorumlar...
    (Toplam 1 yorum var.)


    Sayfa: 1

    Bu yorumu gerçekten şikayet etmek istiyor musunuz ???


    Bir sebep belirtmek isterseniz alttaki kutucuğa yazabilirsiniz...




    Pencereyi Kapat...
  1. 17.12.2015 11:00
    Murat


    Misafir




    Vallahi netteki onca yabancı kaynak arasından bir bu siteyi bulup doyurucu bilgiyi aldım. Normalde hic yorum yazmam ama teşekkür etmeden geçmek olmazdı. :) Ellerinize sağlık.

Yorum Yazın