Python ile GCM (Google Cloud Messaging) Kullanarak Android Cihazlara Push Bildirimleri Gönderme Sunucusu Oluşturma
Push bildirimleri, mobil uygulamaların kullanıcılarıyla etkileşim kurmasının en etkili yollarından biridir. Kullanıcı uygulamayı aktif olarak kullanmıyorken bile, onlara anlık mesajlar, güncellemeler veya hatırlatıcılar göndererek dikkatlerini çekebilir ve uygulamaya geri dönmelerini sağlayabilirler. Bu teknoloji, e-ticaret uygulamalarından haber uygulamalarına, sosyal medyadan oyunlara kadar geniş bir yelpazede kullanılmaktadır.
Bu makalede, Android cihazlara push bildirimleri göndermek için bir sunucu oluşturma sürecini detaylı bir şekilde inceleyeceğiz. Özellikle, Google’ın bulut mesajlaşma hizmeti olan GCM (Google Cloud Messaging) ve onun modern halefi olan FCM (Firebase Cloud Messaging) teknolojilerini Python programlama dili ile nasıl entegre edeceğimizi adım adım açıklayacağız. GCM terimi makale başlığında yer alsa da, güncel ve desteklenen çözüm olan FCM üzerinden ilerleyeceğiz ve GCM’nin neden artık kullanılmadığını açıklayacağız. Python’ın sadeliği ve güçlü kütüphane ekosistemi sayesinde, bu süreci oldukça verimli bir şekilde yönetebiliriz.
Makalenin sonunda, Android uygulamanızın bildirim token’larını kaydedebileceği, bu token’ları kullanarak hedeflenen cihazlara bildirimler gönderebileceği ve olası hataları yönetebileceği temel bir Python sunucusu yapısına sahip olacaksınız. Ayrıca, güvenlik en iyi uygulamaları ve performans ipuçları hakkında da bilgi edineceksiniz.
GCM ve FCM Nedir?
GCM (Google Cloud Messaging), Google tarafından geliştirilen ve geliştiricilerin sunucularından Android cihazlara bildirim mesajları göndermesine olanak tanıyan ücretsiz bir hizmetti. Ancak Google, 2016 yılında GCM’nin yerini alacak olan Firebase Cloud Messaging (FCM) hizmetini duyurdu. FCM, GCM’nin tüm temel yeteneklerini barındırmakla kalmayıp, aynı zamanda daha zengin bir API, daha kolay entegrasyon ve iOS, Web gibi diğer platformlara da destek sunarak daha kapsamlı bir çözüm haline geldi. GCM, 2019 yılında tamamen kullanımdan kaldırıldı, bu nedenle günümüzde push bildirimleri göndermek için Firebase Cloud Messaging (FCM) kullanmak zorunludur. Makalemizde GCM terimi geçse de, tüm pratik uygulamalarımızı ve kod örneklerimizi FCM üzerinden gerçekleştireceğiz.
FCM, temelde üç ana bileşenden oluşur:
* Client Uygulama: Android cihazlarda çalışan mobil uygulamanız. FCM SDK’sını içerir.
* FCM Backend: Google tarafından yönetilen ve mesajları yönlendiren sunucu altyapısı.
* Uygulama Sunucusu (App Server): Bildirimleri göndermek istediğinizde FCM backend’ine istek gönderen kendi sunucunuz (bu makalede Python ile oluşturacağımız sunucu).
Bir bildirim gönderme süreci şu adımları takip eder:
1. Android uygulaması ilk kez başlatıldığında veya token’ı değiştiğinde, FCM SDK’sı cihaz için benzersiz bir “kayıt token’ı” (registration token) alır.
2. Bu kayıt token’ı, uygulamanız tarafından kendi uygulama sunucunuza (Python sunucumuza) gönderilir ve sunucunuzda saklanır.
3. Uygulama sunucunuz bir bildirim göndermek istediğinde, sakladığı kayıt token’larını kullanarak FCM backend’ine bir HTTP isteği gönderir. Bu istek, bildirim başlığını, içeriğini ve diğer isteğe bağlı verileri içerir.
4. FCM backend’i, isteği alır, hedef cihazın çevrimiçi olup olmadığını kontrol eder ve bildirimi uygun şekilde cihaza yönlendirir.
5. Cihazdaki FCM SDK’sı bildirimi alır ve uygulamanıza iletir. Uygulamanız bu bildirimi kullanıcıya gösterir veya arka planda işler.
Ön Gereksinimler
Bu makaledeki adımları takip edebilmek için aşağıdaki ön gereksinimlere sahip olmanız gerekmektedir:
Python Ortamı
* Python 3.x: Sisteminizde Python 3 yüklü olmalıdır. Komut istemcinizde python --version veya python3 --version komutuyla kontrol edebilirsiniz.
* pip: Python paket yöneticisi pip’in güncel olduğundan emin olun. Genellikle Python kurulumuyla birlikte gelir.
Google Hesabı ve Firebase Projesi
* Google Hesabı: Bir Firebase projesi oluşturmak ve yönetmek için aktif bir Google hesabına ihtiyacınız olacak.
* Firebase Projesi: Firebase Console üzerinden bir Firebase projesi oluşturmanız gerekecektir. Bu proje, Android uygulamanızı ve sunucunuzu FCM ile entegre etmek için kullanılacaktır.
Android Geliştirme Ortamı
* Android Studio: Android uygulaması geliştirmek için Android Studio’nun kurulu olması gerekmektedir.
* Temel Android Bilgisi: Android uygulaması oluşturma ve yapılandırma hakkında temel bilgilere sahip olmanız faydalı olacaktır.
Gerekli Kütüphaneler (Python)
Sunucu tarafında push bildirimleri göndermek için Python’da çeşitli kütüphaneler kullanabiliriz. Bu makalede, FCM HTTP v1 API ile doğrudan etkileşim kurmak için requests kütüphanesini ve yetkilendirme için google-auth kütüphanesini kullanacağız. Ayrıca, token’ları kaydetmek ve basit bir API sunmak için Flask web framework’ünü kullanacağız.
Bu kütüphaneleri kurmak için terminalinizde aşağıdaki komutları çalıştırın:
pip install requests google-auth Flask
Alternatif olarak, Google’ın resmi Python SDK’sı olan firebase-admin kütüphanesini de kullanabilirsiniz. Bu kütüphane, FCM ile etkileşimi daha yüksek seviyeli ve daha kolay hale getirir. Ancak, FCM HTTP v1 API’sinin nasıl çalıştığını anlamak adına requests ile ilerleyeceğiz.
Android Uygulama Tarafı Kurulumu
Push bildirimlerini alabilmek için Android uygulamanızda bazı yapılandırmalar yapmanız gerekmektedir.
Firebase Projesi Oluşturma ve Uygulama Ekleme
1. Firebase Console’a Gitme: Tarayıcınızda [https://console.firebase.google.com/](https://console.firebase.google.com/) adresine gidin ve Google hesabınızla oturum açın.
2. Yeni Proje Oluşturma: “Proje Ekle” butonuna tıklayarak yeni bir Firebase projesi oluşturun. Projenize bir isim verin ve gerekli adımları takip edin. Google Analytics ayarlarını isteğinize göre yapılandırabilirsiniz.
3. Android Uygulaması Ekleme: Projeniz oluşturulduktan sonra, proje genel bakış ekranında “Uygulamanıza Firebase ekleyin” bölümünden Android simgesine tıklayın.
4. Uygulama Bilgilerini Girme:
* Android Paket Adı: Android uygulamanızın build.gradle dosyasındaki applicationId ile eşleşmelidir (örneğin, com.example.myapp).
* Uygulama Takma Adı (isteğe bağlı): Uygulamanıza bir isim verin.
* SHA-1 Sertifika Parmak İzi (isteğe bağlı ama önerilir): Google Sign-In gibi hizmetleri kullanmayı planlıyorsanız veya daha güvenli bir kurulum için SHA-1 parmak izini eklemeniz önerilir. Bu, uygulamanızın kimliğini doğrulamak için kullanılır.
* Debug SHA-1’i almak için Android Studio’da sağ üstteki Gradle sekmesini açın, app -> Tasks -> android -> signingReport öğesine çift tıklayın. Çıktıda SHA1: ile başlayan değeri kopyalayın.
5. google-services.json Dosyasını İndirme: Uygulama bilgilerinizi girdikten sonra Firebase, google-services.json adlı bir yapılandırma dosyası oluşturacaktır. Bu dosyayı indirin ve Android Studio projenizin app modülünün kök dizinine (genellikle app/ klasörü) yapıştırın.
Gradle Yapılandırması
google-services.json dosyasını ekledikten sonra, Firebase SDK’sını ve Google Services eklentisini projenize dahil etmeniz gerekir.
1. Proje Seviyesindeki build.gradle (Project: YourProjectName) dosyasına ekleyin:
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
// ... diğer bağımlılıklar
classpath 'com.google.gms:google-services:4.3.15' // En güncel sürümü kullanın
}
}
// ...
2. Uygulama Seviyesindeki build.gradle (Module: app) dosyasına ekleyin:
plugins {
id 'com.android.application'
id 'com.google.gms.google-services' // Bu satırı ekleyin
}
android {
// ...
}
dependencies {
// ... diğer bağımlılıklar
implementation 'com.google.firebase:firebase-bom:32.7.0' // En güncel BOM sürümünü kullanın
implementation 'com.google.firebase:firebase-messaging'
}
Değişiklikleri uyguladıktan sonra Android Studio’da “Sync Project with Gradle Files” butonuna tıklayın.
FCM Kayıt Token’ını Alma
Her cihazın, FCM ile iletişim kurmak için benzersiz bir kayıt token’ına ihtiyacı vardır. Bu token, cihazın uygulamanız için FCM tarafından tanınmasını sağlar. Bu token’ı almak ve sunucumuza göndermek için özel bir servis oluşturmalıyız.
1. FirebaseMessagingService Oluşturma: Uygulamanızda FirebaseMessagingService sınıfından türeyen bir servis oluşturun. Bu servis, yeni token’lar oluşturulduğunda veya mevcut token’lar yenilendiğinde tetiklenir.
package com.example.myapp;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
@Override
public void onNewToken(String token) {
Log.d(TAG, "Refreshed token: " + token);
// TODO: Bu token'ı kendi uygulama sunucunuza gönderin.
// Genellikle bir HTTP POST isteği ile sunucuya gönderilir
// ve sunucunuzda bir veritabanında saklanır.
sendRegistrationToServer(token);
}
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Uygulama ön plandayken gelen mesajları burada işleyebilirsiniz.
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Mesaj bir bildirim içeriyorsa
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
// Burada bildirimi kullanıcıya göstermek için NotificationManager kullanabilirsiniz.
// Örneğin: showNotification(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
}
// Mesaj veri içeriyorsa (data payload)
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
// Veri payload'ını burada işleyebilirsiniz.
}
}
private void sendRegistrationToServer(String token) {
// Bu metodda, token'ı Python sunucumuza göndermek için bir HTTP isteği yapmalıyız.
// Örneğin, Volley veya Retrofit gibi kütüphaneler kullanarak bir POST isteği yapabilirsiniz.
// Örnek bir URL: "http://your_python_server_ip:5000/register_token"
// requestBody: {"token": token}
Log.d(TAG, "Sending token to server: " + token);
// ... (HTTP isteği gönderme kodu buraya gelecek)
}
}
2. AndroidManifest.xml Dosyasına Servisi Ekleme:
Artık uygulamanız her çalıştığında veya token’ı yenilendiğinde onNewToken metodu tetiklenecek ve logcat’te token’ı göreceksiniz. Bu token’ı sendRegistrationToServer metodunda kendi Python sunucunuza göndermeniz gerekecektir.
Bildirimleri Alma ve İşleme
* Uygulama Ön Plandayken: onMessageReceived metodu, uygulamanız ön plandayken bir bildirim geldiğinde tetiklenir. Bu durumda, bildirimi kullanıcıya göstermek için Android’in NotificationManager servisini kullanarak manuel olarak bir bildirim oluşturmanız gerekir.
* Uygulama Arka Plandayken/Kapalıyken: Uygulamanız arka plandayken veya tamamen kapalıyken gelen bildirimler, eğer bildirim payload’u (notification payload) içeriyorsa, FCM SDK’sı tarafından otomatik olarak sistem tepsisinde gösterilir. Kullanıcı bildirime tıkladığında, uygulamanız başlatılır ve bildirimin içerdiği verilerle (eğer varsa) açılır. Eğer sadece veri payload’u (data payload) gönderilmişse, uygulama arka planda olsa bile onMessageReceived metodu çağrılır ve veriyi işleyebilirsiniz.
Python Sunucu Tarafı Kurulumu
Şimdi sıra, Android cihazlara bildirim gönderecek olan Python sunucumuzu kurmaya geldi.
Gerekli Kütüphaneler
Daha önce belirttiğimiz gibi, aşağıdaki kütüphaneleri yüklediğinizden emin olun:
pip install requests google-auth Flask
Firebase Servis Hesabı Oluşturma
Python sunucunuzun Firebase API’leri ile güvenli bir şekilde iletişim kurabilmesi için bir servis hesabı anahtarına ihtiyacı vardır. Bu anahtar, sunucunuzun kimliğini doğrulamak için kullanılır.
1. Firebase Console’a Gitme: Projenizin Firebase Console’una gidin.
2. Proje Ayarları: Sol menüden “Proje Ayarları” (Project settings) seçeneğine tıklayın.
3. Servis Hesapları Sekmesi: “Servis Hesapları” (Service accounts) sekmesine gidin.
4. Yeni Özel Anahtar Oluşturma: “Yeni özel anahtar oluştur” (Generate new private key) düğmesine tıklayın. Bu, bir JSON dosyası indirecektir (örneğin, your-project-name-firebase-adminsdk-xxxxx-xxxxxx.json). Bu dosya, sunucunuzun kimlik bilgilerini içerir ve kesinlikle gizli tutulmalıdır. Bu dosyayı Python projenizin kök dizinine yerleştirin.
API Anahtarı ve Yetkilendirme
FCM HTTP v1 API’si, geleneksel sunucu anahtarı yerine OAuth 2.0 token’ları ile yetkilendirme kullanır. Bu token’ları elde etmek için indirdiğiniz servis hesabı JSON dosyasını kullanacağız. google-auth kütüphanesi bu süreci kolaylaştırır.
import os
import json
import requests
from google.oauth2 import service_account
from google.auth.transport.requests import Request
Firebase servis hesabı anahtarınızın yolu
SERVICE_ACCOUNT_KEY_FILE = 'path/to/your-project-name-firebase-adminsdk-xxxxx-xxxxxx.json'
PROJECT_ID = 'your-firebase-project-id' # Firebase Console'dan proje kimliğinizi alın
def get_access_token():
"""
Firebase servis hesabı kimlik bilgileriyle bir erişim token'ı alır.
"""
try:
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_KEY_FILE,
scopes=['https://www.googleapis.com/auth/firebase.messaging']
)
# Token'ı yenilemek için Request nesnesini kullan
request = Request()
credentials.refresh(request)
return credentials.token
except Exception as e:
print(f"Error getting access token: {e}")
return None
Örnek kullanım:
access_token = get_access_token()
if access_token:
print(f"Access Token: {access_token}")
SERVICE_ACCOUNT_KEY_FILE yolunu ve PROJECT_ID değerini kendi Firebase projenizin bilgileriyle güncellemeyi unutmayın. PROJECT_ID‘yi Firebase Console’da Proje Ayarları -> Genel sekmesinde bulabilirsiniz.
Python ile Push Bildirimi Gönderme
Şimdi, asıl iş olan Python sunucumuzdan Android cihazlara push bildirimi gönderme işlemine geçelim.
Temel Mantık
1. Token Saklama: Android uygulamanızdan gelen kayıt token’larını sunucunuzda güvenli bir şekilde saklamanız gerekir. Gerçek bir uygulamada bu bir veritabanı (PostgreSQL, MySQL, MongoDB vb.) olurdu. Basit bir örnek için, bu makalede bir liste veya JSON dosyası kullanabiliriz.
2. Bildirim Yükü (Payload): FCM’ye gönderdiğimiz her bildirim, bir JSON nesnesi şeklinde bir yük içerir. Bu yük iki ana bölümden oluşabilir:
* notification: Cihazın sistem tepsisinde gösterilecek başlık (title) ve içerik (body) gibi görünen bilgileri içerir.
* data: Uygulamanızın arka planda işleyebileceği özel verileri içerir. Bu veriler anahtar-değer çiftleri şeklinde olabilir ve uygulamanızın belirli bir eylemi gerçekleştirmesi için kullanılabilir.
FCM HTTP v1 API Kullanarak Gönderme
FCM HTTP v1 API’si, bildirim göndermek için kullanılan en güncel ve önerilen yöntemdir.
Endpoint URL’si:
https://fcm.googleapis.com/v1/projects/{PROJECT_ID}/messages:send
Gerekli HTTP Başlıkları:
* Authorization: Bearer : get_access_token() fonksiyonundan aldığımız erişim token’ı.
* Content-Type: application/json: İstek gövdesinin JSON formatında olduğunu belirtir.
JSON İstek Gövdesi:
İstek gövdesi, bir message objesi içermelidir. Bu message objesi, hedefleme (token, topic, condition), bildirim (notification) ve veri (data) alanlarını içerir.
import requests
import json
from google.oauth2 import service_account
from google.auth.transport.requests import Request
Firebase servis hesabı anahtarınızın yolu ve proje kimliğiniz
SERVICE_ACCOUNT_KEY_FILE = 'your-project-name-firebase-adminsdk-xxxxx-xxxxxx.json'
PROJECT_ID = 'your-firebase-project-id'
def get_access_token():
"""
Firebase servis hesabı kimlik bilgileriyle bir erişim token'ı alır.
"""
try:
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_KEY_FILE,
scopes=['https://www.googleapis.com/auth/firebase.messaging']
)
request = Request()
credentials.refresh(request)
return credentials.token
except Exception as e:
print(f"Error getting access token: {e}")
return None
def send_fcm_notification(registration_token, title, body, data=None):
"""
Belirtilen kayıt token'ına FCM bildirimi gönderir.
"""
access_token = get_access_token()
if not access_token:
print("Failed to get access token. Cannot send notification.")
return False
headers = {
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/json'
}
message = {
'message': {
'token': registration_token,
'notification': {
'title': title,
'body': body,
},
'data': data if data else {}, # Özel veriler
}
}
fcm_send_url = f'https://fcm.googleapis.com/v1/projects/{PROJECT_ID}/messages:send'
try:
response = requests.post(fcm_send_url, headers=headers, data=json.dumps(message))
response.raise_for_status() # HTTP hata durumlarını yakala (4xx veya 5xx)
print(f"FCM response status: {response.status_code}")
print(f"FCM response body: {response.json()}")
return True
except requests.exceptions.RequestException as e:
print(f"Error sending FCM message: {e}")
if response is not None:
print(f"Response content: {response.text}")
return False
# Örnek kullanım:
# Android uygulamanızdan aldığınız bir kayıt token'ı
test_token = "YOUR_ANDROID_DEVICE_REGISTRATION_TOKEN_HERE"
# if send_fcm_notification(test_token, "Merhaba Python!", "Bu bir Python sunucusundan gelen bildirimdir.", {"key": "value"}):
print("Bildirim başarıyla gönderildi.")
else:
print("Bildirim gönderilirken hata oluştu.")
Bu kod parçası, get_access_token fonksiyonu ile bir erişim token’ı alır ve ardından send_fcm_notification fonksiyonu ile belirtilen bir kayıt token’ına bildirim gönderir. data parametresi ile özel veriler de ekleyebilirsiniz.
Çoklu Cihazlara Gönderme ve Konular (Topics)
Tek tek token’lara bildirim göndermenin yanı sıra, FCM daha esnek hedefleme seçenekleri sunar:
* Çoklu Cihazlara Tek Tek Gönderme: Eğer birçok cihaza aynı anda bildirim göndermek istiyorsanız, her bir token için ayrı ayrı send_fcm_notification fonksiyonunu çağırabilir veya FCM’nin toplu mesajlaşma (batch messaging) özelliğini kullanabilirsiniz (ancak bu, daha karmaşık bir API kullanımı gerektirir).
* Konulara (Topics) Gönderme: Cihazların belirli konulara abone olmasını sağlayabilirsiniz (örneğin, “haberler”, “spor”). Bu durumda, bildirim gönderirken token yerine topic alanını kullanırsınız:
{
"message": {
"topic": "news",
"notification": {
"title": "Son Dakika!",
"body": "Yeni bir haber yayında."
}
}
}
Android tarafında bir cihaza konuya abone olmak için:
FirebaseMessaging.getInstance().subscribeToTopic("news")
.addOnCompleteListener(task -> {
String msg = "Subscribed to news topic";
if (!task.isSuccessful()) {
msg = "Subscribe failed";
}
Log.d(TAG, msg);
});
* Koşullara (Conditions) Gönderme: Daha karmaşık hedefleme için condition alanını kullanabilirsiniz. Bu, birden fazla konuya abone olan veya belirli bir konuya abone olmayan cihazlara bildirim göndermenizi sağlar:
{
"message": {
"condition": "'stock' in topics && ('weather' in topics || 'news' in topics)",
"notification": {
"title": "Özel Bildirim",
"body": "Hisse senedi ve hava durumu/haberler ile ilgilenenlere."
}
}
}
Hata Yönetimi ve Yeniden Denemeler
FCM API’sinden gelen yanıtları dikkatlice incelemek önemlidir. Olası hatalar şunları içerebilir:
* INVALID_ARGUMENT: İstek gövdesi veya başlıklarında bir hata var.
* UNREGISTERED: Gönderilen token artık geçerli değil (cihaz uygulamayı kaldırmış veya token yenilenmiş). Bu token’ları veritabanınızdan silmeniz gerekir.
* UNAVAILABLE: Geçici bir FCM hatası. Belirli bir gecikmeyle yeniden deneme yapabilirsiniz (exponential backoff).
* NOT_FOUND: Belirtilen proje kimliği bulunamadı.
send_fcm_notification fonksiyonumuzda response.raise_for_status() ile temel HTTP hatalarını yakalıyoruz. Daha detaylı hata yönetimi için response.json() içeriğini kontrol etmek ve belirli hata kodlarına göre işlem yapmak gerekir. Geçersiz token’ları veritabanınızdan otomatik olarak temizlemek, gelecekteki bildirim gönderme işlemlerinizin verimliliğini artıracaktır.
Python Sunucusu Örneği (Flask ile Basit Bir API)
Şimdi tüm parçaları bir araya getirerek, token’ları kaydedebilen ve bildirim gönderebilen basit bir Flask tabanlı sunucu oluşturalım.
from flask import Flask, request, jsonify
import json
import os
import requests
from google.oauth2 import service_account
from google.auth.transport.requests import Request
app = Flask(__name__)
--- FCM Yetkilendirme ve Gönderme Fonksiyonları ---
Firebase servis hesabı anahtarınızın yolu ve proje kimliğiniz
Güvenlik için bu bilgileri ortam değişkenlerinden veya güvenli bir yapılandırma dosyasından okuyun.
Örnek: os.environ.get('FIREBASE_SERVICE_ACCOUNT_KEY_PATH')
SERVICE_ACCOUNT_KEY_FILE = 'your-project-name-firebase-adminsdk-xxxxx-xxxxxx.json'
PROJECT_ID = 'your-firebase-project-id'
Token'ları saklamak için basit bir liste. Gerçek uygulamada bir veritabanı kullanmalısınız.
Bu liste, sunucu yeniden başlatıldığında sıfırlanacaktır.
registered_tokens = []
Token'ları kalıcı olarak saklamak için basit bir JSON dosyası kullanalım
TOKEN_FILE = 'registered_tokens.json'
def load_tokens():
if os.path.exists(TOKEN_FILE):
with open(TOKEN_FILE, 'r') as f:
return json.load(f)
return []
def save_tokens(tokens):
with open(TOKEN_FILE, 'w') as f:
json.dump(tokens, f)
registered_tokens = load_tokens()
def get_access_token():
try:
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_KEY_FILE,
scopes=['https://www.googleapis.com/auth/firebase.messaging']
)
request = Request()
credentials.refresh(request)
return credentials.token
except Exception as e:
print(f"Error getting access token: {e}")
return None
def send_fcm_notification(registration_token, title, body, data=None):
access_token = get_access_token()
if not access_token:
print("Failed to get access token. Cannot send notification.")
return False
headers = {
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/json'
}
message = {
'message': {
'token': registration_token,
'notification': {
'title': title,
'body': body,
},
'data': data if data else {},
}
}
fcm_send_url = f'https://fcm.googleapis.com/v1/projects/{PROJECT_ID}/messages:send'
try:
response = requests.post(fcm_send_url, headers=headers, data=json.dumps(message))
response.raise_for_status()
response_data = response.json()
print(f"FCM response status: {response.status_code}")
print(f"FCM response body: {response_data}")
# Hata durumlarını kontrol et ve geçersiz token'ları sil
if 'error' in response_data:
error_code = response_data['error'].get('status')
if error_code == 'UNREGISTERED' or error_code == 'NOT_FOUND':
print(f"Token {registration_token} is invalid or unregistered. Removing from list.")
global registered_tokens
registered_tokens = [t for t in registered_tokens if t != registration_token]
save_tokens(registered_tokens)
return False
return True
except requests.exceptions.RequestException as e:
print(f"Error sending FCM message to {registration_token}: {e}")
if response is not None:
print(f"Response content: {response.text}")
return False
--- Flask API Endpoints ---
@app.route('/')
def home():
return "FCM Push Notification Server is running!"
@app.route('/register_token', methods=['POST'])
def register_token():
"""
Android cihazlardan gelen FCM kayıt token'larını kaydeder.
İstek gövdesi: {"token": "cihaz_token_buraya"}
"""
token_data = request.get_json()
if not token_data or 'token' not in token_data:
return jsonify({"error": "Token missing"}), 400
token = token_data['token']
if token not in registered_tokens:
registered_tokens.append(token)
save_tokens(registered_tokens)
print(f"Token registered: {token}")
return jsonify({"message": "Token registered successfully"}), 200
else:
print(f"Token already registered: {token}")
return jsonify({"message": "Token already registered"}), 200
@app.route('/send_notification', methods=['POST'])
def send_notification():
"""
Kayıtlı tüm cihazlara push bildirimi gönderir.
İstek gövdesi: {"title": "Bildirim Başlığı", "body": "Bildirim İçeriği", "data": {"key": "value"}}
"""
notification_data = request.get_json()
if not notification_data or 'title' not in notification_data or 'body' not in notification_data:
return jsonify({"error": "Title or body missing"}), 400
title = notification_data['title']
body = notification_data['body']
data = notification_data.get('data', {})
if not registered_tokens:
return jsonify({"message": "No tokens registered to send notifications"}), 200
success_count = 0
failure_count = 0
for token in list(registered_tokens): # Liste üzerinde değişiklik yaparken kopyasını kullan
if send_fcm_notification(token, title, body, data):
success_count += 1
else:
failure_count += 1
# send_fcm_notification zaten geçersiz token'ları listeden siliyor.
return jsonify({
"message": f"Notifications sent. Success: {success_count}, Failure: {failure_count}",
"total_tokens_after_send": len(registered_tokens)
}), 200
if __name__ == '__main__':
# Flask uygulamasını çalıştırma
# Debug modunu üretim ortamında KAPALI tutun!
app.run(host='0.0.0.0', port=5000, debug=True)
Kullanım Notları:
1. SERVICE_ACCOUNT_KEY_FILE ve PROJECT_ID değişkenlerini kendi Firebase projenizin değerleriyle güncelleyin. Servis hesabı JSON dosyasının sunucunuzla aynı dizinde olduğundan emin olun veya doğru yolu belirtin.
2. Bu örnekte token’ları basit bir JSON dosyasına kaydediyoruz. Gerçek bir uygulamada, ölçeklenebilirlik ve güvenlik için bir veritabanı kullanmalısınız.
3. Uygulamayı çalıştırmak için terminalinizde python your_server_file_name.py komutunu kullanın. Sunucu varsayılan olarak http://0.0.0.0:5000 adresinde çalışacaktır.
4. Android uygulamanızdan /register_token endpoint’ine POST isteği göndererek token’ları kaydedin.
5. send_notification endpoint’ine POST isteği göndererek kayıtlı tüm cihazlara bildirim gönderin.
Örnek API İstekleri (Postman/cURL ile):
* Token Kaydı:
curl -X POST -H "Content-Type: application/json" -d '{"token": "YOUR_ANDROID_DEVICE_REGISTRATION_TOKEN"}' http://YOUR_SERVER_IP:5000/register_token
* Bildirim Gönderme:
curl -X POST -H "Content-Type: application/json" -d '{"title": "Yeni Bildirim!", "body": "Uygulamanızdan önemli bir mesaj.", "data": {"type": "promo", "id": "123"}}' http://YOUR_SERVER_IP:5000/send_notification
Güvenlik ve En İyi Uygulamalar
Push bildirim sunucusu geliştirirken güvenlik ve performans, dikkat edilmesi gereken kritik noktalardır.
* API Anahtarlarının Güvenliği: Firebase servis hesabı JSON dosyanız ve diğer API anahtarlarınız son derece gizli tutulmalıdır.
* Bu dosyayı asla istemci tarafında (Android uygulaması içinde) kullanmayın.
* Versiyon kontrol sistemlerine (Git gibi) doğrudan yüklemekten kaçının. .gitignore dosyasına ekleyin.
* Üretim ortamında, bu tür hassas bilgileri ortam değişkenleri, bulut tabanlı gizli yönetim hizmetleri (örneğin, Google Secret Manager, AWS Secrets Manager) veya şifrelenmiş yapılandırma dosyaları aracılığıyla yönetin.
* Token Yönetimi:
* Geçersiz Token’ları Temizleme: FCM API’si bir token’ın geçersiz olduğunu veya artık kayıtlı olmadığını bildirdiğinde (örneğin, UNREGISTERED hatası), bu token’ı veritabanınızdan derhal silmelisiniz. Bu, gereksiz API çağrılarını önler ve sisteminizin performansını artırır.
* Token Güncelleme: Cihazın kayıt token’ı zaman zaman değişebilir. onNewToken metodu tetiklendiğinde, yeni token’ı sunucunuza göndererek mevcut token’ı güncellemeniz veya yerine yenisini eklemeniz gerekir.
* Güvenli Saklama: Token’ları veritabanınızda güvenli bir şekilde saklayın.
* Veri Gizliliği ve Hassasiyet:
* Hassas kişisel bilgileri veya gizli verileri doğrudan bildirim payload’unda göndermekten kaçının. Bunun yerine, bir kimlik (ID) gönderin ve uygulamanın bu kimliği kullanarak sunucunuzdan güvenli bir API çağrısı ile veriyi çekmesini sağlayın.
* Hız Sınırları (Rate Limiting): FCM, belirli hız sınırlarına sahiptir. Çok sayıda bildirim gönderiyorsanız, bu sınırları aşmamaya dikkat edin. Toplu bildirimler için FCM’nin desteklediği yöntemleri kullanmak veya kendi tarafınızda bir kuyruk sistemi (örneğin, Celery ile Redis/RabbitMQ) kurarak bildirim gönderme işlemlerini yavaşlatmak faydalı olabilir.
* Hata İzleme ve Günlük Kaydı: Bildirim gönderme işlemlerindeki başarı ve başarısızlıkları izleyin. Hata günlüklerini tutarak sorunları hızlı bir şekilde tespit edebilir ve çözebilirsiniz.
* Sunucu Güvenliği: Flask uygulamanızı üretim ortamında çalıştırırken bir WSGI sunucusu (Gunicorn, uWSGI) arkasında çalıştırmalı ve bir ters proxy (Nginx, Apache) ile korumalısınız. Güvenlik duvarları, SSL/TLS şifrelemesi ve diğer standart sunucu güvenliği uygulamalarını uygulayın.
Sonuç
Bu makalede, Python kullanarak Android cihazlara Firebase Cloud Messaging (FCM) aracılığıyla push bildirimleri göndermek için bir sunucu oluşturma sürecini ayrıntılı olarak inceledik. GCM’den FCM’ye geçişi, Android uygulama tarafında yapılması gereken yapılandırmaları, kayıt token’larının nasıl alınacağını ve sunucuya nasıl gönderileceğini öğrendik. Ardından, Python sunucumuzda Firebase servis hesabı yetkilendirmesini ve FCM HTTP v1 API’sini kullanarak bildirim gönderme mekanizmasını adım adım uyguladık. Son olarak, Flask framework’ü ile basit bir API sunucusu örneği oluşturarak token kaydı ve bildirim gönderme işlevlerini bir araya getirdik ve önemli güvenlik ve en iyi uygulamalar hakkında bilgi verdik.
Artık, uygulamanızın kullanıcılarıyla etkileşimi artırmak, önemli güncellemeleri anında iletmek veya hedeflenmiş pazarlama kampanyaları yürütmek için güçlü bir push bildirim altyapısına sahipsiniz. Bu temel yapıyı kullanarak, daha gelişmiş hedefleme, bildirim zamanlama, çoklu platform desteği ve daha sağlam hata yönetimi gibi özellikleri entegre ederek uygulamanızın bildirim yeteneklerini daha da genişletebilirsiniz. Unutmayın, push bildirimlerinin gücünü akıllıca ve kullanıcı deneyimini zenginleştirecek şekilde kullanmak, uygulamanızın başarısı için kritik öneme sahiptir.