Android 플랫폼에서 푸시 알림


266

서버에서 푸시 알림을 수신하는 앱을 작성하려고합니다. 이 작업을 수행하는 몇 가지 방법을 찾았습니다.

  1. SMS-수신 SMS를 가로 채 서버에서 가져 오기 시작
  2. 서버를 주기적으로 폴링

각각 고유 한 제한이 있습니다. SMS- 도착 시간에 대한 보장은 없습니다. 폴링으로 인해 배터리가 방전 될 수 있습니다.

더 나은 제안이 있으십니까? 매우 감사합니다.


4
또한 구글 I / 푸시 알림에 대한 O 2010 프리젠 테이션 볼 수 developer.android.com/videos/index.html#v=PLM4LajwDVc
vokilam

이 게시물을 볼 수 있다고 생각합니다 : stackoverflow.com/questions/17629942/… Worklight를 사용하면 GCM을 포함한 다른 채널을 통해 푸시를받을 수 있습니다.
Neeraj Krishna

1
Google I / O 2010 프레젠테이션은 youtube.com/watch?v=PLM4LajwDVc
elcuco

"폴은 배터리를 방전시킬 수 있습니다." AlarmManager로 폴링을 해제 할 수 있으므로 배터리가 많이 소모되지 않습니다. 간단하고 무료입니다 (GCM과 같이 지불 할 필요가 없음).
Deepscorn

답변:


203

Google의 공식 답변은 Android Cloud to Device Messaging Framework (더 이상 사용되지 않음) Google Cloud Messaging (더 이상 사용되지 않음) Firebase Cloud Messaging입니다.

Android> = 2.2 (Play Store가있는 전화기)에서 작동합니다.


현재 베타 버전이지만 활성화되기를 희망하며 가입 할 수 있습니다.
brack

3
일반적으로 매우 빠르게 활성화 할 수 있으며 Gmail과 같은 용도로 사용되므로 프로덕션 환경에서 작동하는 것으로 알려져 있습니다. 불행히도 C2DM의 서버 측 측면과 통신하기위한 샘플 코드가 부족합니다. 이 부분에 대한 자습서를 작성했습니다. blog.boxedice.com/2010/10/07/…
DavidM

6
문제는 사용자를 위해 Google 계정이 필요하다는 것입니다.
kaffein

33
Android 클라우드 대 장치 메시징 프레임 워크는 더 이상 사용되지 않습니다. 새 프레임 워크를 Google 클라우드 메시징이라고하며 여기에서 찾을 수 있습니다. developer.android.com/guide/google/gcm/index.html
Ryan Berger

2018 년 4 월 10 일 Google은 GCM을 더 이상 사용하지 않습니다. GCM 서버 및 클라이언트 API는 2019 년 5 월 29 일에 제거되었습니다. GCM 앱을 FCM (Firebase Cloud Messaging)으로 마이그레이션하십시오. 자세한 내용은 마이그레이션 안내서를 참조하십시오.
paiego

29

( 비슷한 질문에 대한 답변에서 교차 게시-Android는 거의 실시간 푸시 알림을 지원합니까? )

나는 최근에 이런 종류의 일을하는 방법으로 안드로이드 용 MQTT http://mqtt.org 를 사용 하기 시작했습니다 (즉, SMS가 아닌 데이터 기반, 거의 즉각적인 메시지 전달, 폴링이 아닌 푸시 알림)

도움이되는 경우 배경 정보가있는 블로그 게시물이 있습니다.

http://dalelane.co.uk/blog/?p=938

(참고 : MQTT는 IBM 기술이므로 IBM에서 일하고 있음을 지적해야합니다.)


안녕하세요 Dale, MQTT에 대한 귀하의 블로그 게시물을 읽었으며 모바일에 대한 거의 즉각적인 알림에 대한 청구서에 확실히 맞는 것 같습니다. 그러나 실제로 어떻게 작동하는지에 대한 정보를 찾을 수 없었습니다. 소켓이 항상 열려 있습니까? IP 주소가 변경된 경우 서버에 어떻게 알립니 까? 이것에 약간의 빛을 비출 수 있다면 고맙겠습니다. 건배 나렌
나렌

2
연결이 열린 상태로 유지됩니다. 후속 게시물 ( dalelane.co.uk/blog/?p=1009 )에서 나는 연결을 유지하는 것의 의미에 대해 더 많이 이야기했습니다. 연결이 끊어지면 서버와 클라이언트 모두에게 알릴 수 있습니다. 그런 다음 응답 방법 (예 : 다시 연결)을 결정하는 응용 프로그램 계층 결정입니다. 게시물에 언급 된 문서에 대한 자세한 정보가 있습니다 (예 : IA92 : www-01.ibm.com/support/docview.wss?rs=171&uid=swg24006006 pdf 및 해당 페이지의 zip에있는 Javadoc)
dalelane

18

Android 푸시 알림에 대한 나의 이해 / 경험은 다음과 같습니다.

  1. C2DM GCM은 - 대상 안드로이드 플랫폼 2.2의 경우, 그것을 위해 이동합니다. 메시지를 받으려면장치 사용자는 항상 Google 계정 으로 로그인 해야합니다.

  2. MQTT -Pub / Sub 기반 접근 방식으로, 장치와의 활성 연결이 필요하며, 현명하게 구현되지 않으면 배터리가 소모 될 수 있습니다.

  3. 집사 -제한된 지역 사회 지원으로 인해 장기적으로 좋지 않을 수 있습니다.

편집 : 2013 년 11 월 25 일에 추가됨

GCM -Google에 따르면 ...

3.0 이전 기기의 경우 사용자는 휴대 기기에서 Google 계정을 설정해야합니다. Android 4.0.4 이상을 실행하는 기기에서는 Google 계정이 필요하지 않습니다. *


4.0.4 이상에서는 Google 계정이 필요하지 않지만 Google Play 앱을 설치해야합니다. Google 계정이 없어도 설치 방법이 궁금합니다.
1

1
@Jan : Google Play 앱은 기기와 함께 제공됩니다. 사용자는 설치할 필요가 없습니다.
Dexter

@Dexter, 모든 Android 기기에 기본적으로 Google Play가 설치되어있는 것은 아닙니다. 대부분 평판이 좋은 전화 공급 업체에서 구매 한 기기가 기본적으로 설치되어 있지만 Android OS 만 플래시 한 기기에 항상 Google Play가있는 것은 아닙니다. (예를 들어, 새로운 Genymotion 기기와 같은 많은 Android 에뮬레이터에는 기본적으로 Google Play가 없습니다.)
Spencer D

그렇다면 ... Google Play가 설치되지 않은 Android 기기에 MQTT가 가장 적합한 옵션입니까?
Yeung

17

Android 클라우드-장치 메시징 프레임 워크

중요 : C2DM은 2012 년 6 월 26 일부터 공식적으로 사용되지 않습니다. 이는 C2DM이 새 사용자 및 할당량 요청 수락을 중단했음을 의미합니다. C2DM에는 새로운 기능이 추가되지 않습니다. 그러나 C2DM을 사용하는 앱은 계속 작동합니다. 기존 C2DM 개발자는 Google Cloud Messaging for Android (GCM)라는 새로운 C2DM 버전으로 마이그레이션하는 것이 좋습니다. 자세한 정보는 C2DM에서 GCM으로의 마이그레이션 문서를 참조하십시오. 개발자는 새로운 개발을 위해 GCM을 사용해야합니다.

다음 링크를 확인하십시오.

http://developer.android.com/guide/google/gcm/index.html


17

여기에서 처음부터 RegID 및 알림을 얻는 방법에 대한 몇 가지 단계를 작성했습니다.

  1. Google Cloud에서 앱 생성 / 등록
  2. 개발 환경 설정 Cloud SDK
  3. GCM을위한 프로젝트 구성
  4. 장치 등록 ID 받기
  5. 푸시 알림 보내기
  6. 푸시 알림 수신

URL 링크 아래에서 전체 자습서를 찾을 수 있습니다

Android 푸시 알림 시작하기 : 최신 Google 클라우드 메시징 (GCM)-단계별 튜토리얼 완료

여기에 이미지 설명을 입력하십시오

등록 ID (푸시 알림 용 장치 토큰)를 가져 오는 코드 조각

GCM을위한 프로젝트 구성


AndroidManifest 파일 업데이트

프로젝트에서 GCM을 사용하려면 매니페스트 파일에 권한을 거의 추가하지 않아도됩니다. AndroidManifest.xml로 이동하여 아래 코드를 추가하십시오. 권한 추가

<uses-permission android:name="android.permission.INTERNET”/>
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<uses-permission android:name="android.permission.VIBRATE" />

<uses-permission android:name=“.permission.RECEIVE" />
<uses-permission android:name=“<your_package_name_here>.permission.C2D_MESSAGE" />
<permission android:name=“<your_package_name_here>.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />

GCM Broadcast Receiver 선언 추가

애플리케이션 태그에 GCM Broadcast Receiver 선언 추가

<application
        <receiver
            android:name=".GcmBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.SEND" ]]>
            <intent-filter]]>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <category android:name="" />
            </intent-filter]]>

        </receiver]]>
     
<application/>

GCM Servie 선언 추가

<application
     <service android:name=".GcmIntentService" />
<application/>

등록 ID 받기 (푸시 알림 용 장치 토큰)

이제 시작 / 스플래시 활동으로 이동

상수 및 클래스 변수 추가

private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
public static final String EXTRA_MESSAGE = "message";
public static final String PROPERTY_REG_ID = "registration_id";
private static final String PROPERTY_APP_VERSION = "appVersion";
private final static String TAG = "LaunchActivity";
protected String SENDER_ID = "Your_sender_id";
private GoogleCloudMessaging gcm =null;
private String regid = null;
private Context context= null;

OnCreate 및 OnResume 메소드 업데이트

@Override
protected void onCreate(Bundle savedInstanceState)
{
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_launch);
     context = getApplicationContext();
         if (checkPlayServices()) 
     {
            gcm = GoogleCloudMessaging.getInstance(this);
            regid = getRegistrationId(context);

            if (regid.isEmpty())
            {
                registerInBackground();
            }
            else
            {
            Log.d(TAG, "No valid Google Play Services APK found.");
            }
      }
 }

@Override protected void onResume()
{
       super.onResume();       checkPlayServices();
}


# Implement GCM Required methods (Add below methods in LaunchActivity)

private boolean checkPlayServices() {
        int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (resultCode != ConnectionResult.SUCCESS) {
            if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
                GooglePlayServicesUtil.getErrorDialog(resultCode, this,
                        PLAY_SERVICES_RESOLUTION_REQUEST).show();
            } else {
                Log.d(TAG, "This device is not supported - Google Play Services.");
                finish();
            }
            return false;
        }
        return true;
 }

private String getRegistrationId(Context context) 
{
   final SharedPreferences prefs = getGCMPreferences(context);
   String registrationId = prefs.getString(PROPERTY_REG_ID, "");
   if (registrationId.isEmpty()) {
       Log.d(TAG, "Registration ID not found.");
       return "";
   }
   int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
   int currentVersion = getAppVersion(context);
   if (registeredVersion != currentVersion) {
        Log.d(TAG, "App version changed.");
        return "";
    }
    return registrationId;
}

private SharedPreferences getGCMPreferences(Context context) 
{
    return getSharedPreferences(LaunchActivity.class.getSimpleName(),
                Context.MODE_PRIVATE);
}

private static int getAppVersion(Context context) 
{
     try 
     {
         PackageInfo packageInfo = context.getPackageManager()
                    .getPackageInfo(context.getPackageName(), 0);
            return packageInfo.versionCode;
      } 
      catch (NameNotFoundException e) 
      {
            throw new RuntimeException("Could not get package name: " + e);
      }
}


private void registerInBackground() 
{     new AsyncTask() {
     Override
     protected Object doInBackground(Object... params) 
     {
          String msg = "";
          try 
          {
               if (gcm == null) 
               {
                        gcm = GoogleCloudMessaging.getInstance(context);
               }
               regid = gcm.register(SENDER_ID);               Log.d(TAG, "########################################");
               Log.d(TAG, "Current Device's Registration ID is: "+msg);     
          } 
          catch (IOException ex) 
          {
              msg = "Error :" + ex.getMessage();
          }
          return null;
     }     protected void onPostExecute(Object result) 
     { //to do here };
  }.execute(null, null, null);
}

노트 : REGISTRATION_KEY를 저장 . PN 메시지를 GCM에 전송하는 것이 중요합니다.이를 사용하면 GCM 만 푸시 알림을 전송하여 모든 장치에 고유합니다.

푸시 알림 수신

GCM 브로드 캐스트 수신기 클래스 추가

이미 매니페스트 파일에“GcmBroadcastReceiver.java”를 선언 했으므로이 클래스 업데이트 수신기 클래스 코드를 이런 식으로 만들 수 있습니다

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) 
    {        ComponentName comp = new ComponentName(context.getPackageName(),
                GcmIntentService.class.getName());        startWakefulService(context, (intent.setComponent(comp)));
        setResultCode(Activity.RESULT_OK);
        Toast.makeText(context, wow!! received new push notification", Toast.LENGTH_LONG).show();
    }
}

GCM 서비스 클래스 추가

이미 매니페스트 파일에“GcmBroadcastReceiver.java”를 선언 했으므로이 클래스 업데이트 수신기 클래스 코드를 이런 식으로 만들 수 있습니다

public class GcmIntentService extends IntentService
{     public static final int NOTIFICATION_ID = 1;     private NotificationManager mNotificationManager;     private final static String TAG = "GcmIntentService";     public GcmIntentService() {
     super("GcmIntentService");     
     }     @Override
     protected void onHandleIntent(Intent intent) {
          Bundle extras = intent.getExtras();
          Log.d(TAG, "Notification Data Json :" + extras.getString("message"));

          GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
          String messageType = gcm.getMessageType(intent);          if (!extras.isEmpty()) {          if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR
               .equals(messageType)) {
               sendNotification("Send error: " + extras.toString());
          } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
          .equals(messageType)) {
          sendNotification("Deleted messages on server: "
          + extras.toString());          // If it's a regular GCM message, do some work.
          } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
          .equals(messageType)) {
          // This loop represents the service doing some work.
          for (int i = 0; i < 5; i++) {
               Log.d(TAG," Working... " + (i + 1) + "/5 @ "
               + SystemClock.elapsedRealtime());               try {
                    Thread.sleep(5000);
               } catch (InterruptedException e) {
               }
             }
             Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime());
             sendNotification(extras.getString("message"));
           }
        }        // Release the wake lock provided by the WakefulBroadcastReceiver.
        GcmBroadcastReceiver.completeWakefulIntent(intent);
     }     // Put the message into a notification and post it.
     // This is just one simple example of what you might choose to do with
     // a GCM message.
     private void sendNotification(String msg) {          mNotificationManager = (NotificationManager) this
          .getSystemService(Context.NOTIFICATION_SERVICE);
          PendingIntent contentIntent = PendingIntent.getActivity(this, 0,          new Intent(this, LaunchActivity.class), 0);

          NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(          this)
          .setSmallIcon(R.drawable.icon)
          .setContentTitle("Ocutag Snap")
          .setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
          .setContentText(msg)
          .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE);

          mBuilder.setContentIntent(contentIntent);          mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
     }
}

@Rohit은 튜토리얼이 완료된 링크 를 확인했습니다 . 또한 누락 된 내용을 알려 주시면 답변을 업데이트하겠습니다.
swiftBoy

11

Meteor 웹 서버를 기반으로 Android에서 푸시 알림을위한 Java 라이브러리를 개발하려는 새로운 오픈 소스 노력이 있습니다. Deacon Project Blog 에서 확인할 수 있습니다 . 여기서 Meteor 및 프로젝트의 GitHub 저장소에 대한 링크를 찾을 수 있습니다. 우리는 개발자가 필요하므로 단어를 전파하십시오!


9

Xtify ( http://developer.xtify.com )를 사용할 수 있습니다 . SDK와 함께 작동하는 푸시 알림 웹 서비스가 있습니다. 무료이며 지금까지는 정말 잘 작동했습니다.


3
푸시 서비스 요금을 청구 할 계획이 없다고 VP의 답변을 받았습니다. 꽤 놀라운 SDK입니다.
Crowe T. Robot

8

또는....

3) 서버에 연결을 유지하고 몇 분마다 연결 유지를 전송하면 서버가 메시지를 즉시 푸시 할 수 있습니다. Gmail, Google 토크 등이 작동하는 방식입니다.


5
슬프게도 이로 인해 많은 양의 배터리가 소모 될 것이라고 생각합니다. 이 길을 타면 시간을 제한하십시오.
haseman

유휴 TCP / IP 연결은 셀 모뎀의 전원을 거의 사용하지 않기 때문에 실제로는 그렇지 않습니다.
Isaac Waller

실제로, 시간이 지남에 따라 많은 시간이 소요될 수 있습니다. 간격이 긴 Keep-Alive를 보내면 많은 도움이됩니다.
Isaac Waller

이와 관련하여 "긴 간격"이란 무엇입니까? Gmail 푸시가 이와 같이 작동한다는 것을 알고 있지만 사용하는 시간 초과 간격을 모르겠습니다.
tobsen 2009

배터리 성능에 대한이 이미지를 찾았습니다. Pull vs Push : labs.ericsson.com/files/battery.jpg Ericsson Push API에서 가져 왔습니다 : labs.ericsson.com/apis/mobile-java-push/documentation
Menda

6

GCM (Android 용 Google 클라우드 메시징)을 사용하는 것이 좋습니다. 무료이며 간단한 용도로는 매우 쉽습니다.

그러나 귀하를 대신하여 알림을 보내려면 제 3의 서버를 유지해야합니다. Android 푸시 알림 서비스를위한 매우 우수한 산업용 솔루션이있는 것을 피하려면 다음을 수행하십시오.

  • Urban Airship-한 달에 최대 1M 알림을 무료로 제공 한 후 1000 알림마다 요금이 청구됩니다
  • PushApps- 매월 1M 알림은 무료이며 매월 19.99 알림은 무제한
  • PushWoosh -1M 기기 무료, 프리미엄 요금제는 39 EURO

면책 조항 -저는 PushApps 에서 일하고 있으며 1 년 이상 내 응용 프로그램에서도 해당 제품을 사용합니다.



4

두 가지 가능한 방법을 모두 찾은 것 같습니다. 구글은 적어도 처음에는 푸시 / 풀 구현에 사용할 수있는 GChat API를 구현하려고했다. 안타깝게도 그 라이브러리는 Android 1.0에 의해 차단되었습니다.


1
보안 문제가 해결되면 다시 가져 오겠다고 약속했습니다.
Jeremy Logan

3

이것이 여전히 유용한 지 모르겠습니다. Java 라이브러리에서 이와 같은 것을 달성했습니다.http://www.pushlets.com/ .

서비스에서 그것을 수행해도 안드로이드가 리스너 스레드를 죽이는 것을 막지 못합니다.



2

C2DM : 앱 사용자는 Gmail 계정이 있어야합니다.

MQTT : 연결이 1024에 도달하면 Linux의 "select model"을 사용했기 때문에 작동이 중지됩니다.

안드로이드를위한 무료 푸시 서비스와 API가 있습니다, 당신은 그것을 시도 할 수 있습니다 : http://push-notification.org


2

자유롭고 쉬운 방법 :

대상 사용자 수가 크지 않고 (1000 미만) 무료 서비스를 시작하려면 Airbop이 가장 편리합니다.

Airbop 웹 사이트 API를 통해 Google 클라우드 메시징 서비스를 사용하며 우수한 성능을 제공합니다. 내 프로젝트 중 두 가지에 사용했으며 쉽게 구현할 수있었습니다.

Urbanship과 같은 서비스는 훌륭하지만 푸시 알림뿐만 아니라 전체 배포 스택을 제공합니다.

푸시 서비스 만 목표 인 경우 Airbop이 제대로 작동합니다.

나는 사용하지 않았다 Pushwoosh를 않았지만 훌륭한 선택입니다. 1,000,000 개의 기기를 무료로 푸시 할 수 있습니다


1

SMS와 HTTP를 모두 사용하는 것이 좋습니다. 사용자가 로그인하지 않은 경우 대기중인 메시지가 있음을 알리기 위해 휴대 전화에 SMS를 보냅니다.

이것이 Ericsson Labs 서비스의 작동 방식입니다. https://labs.ericsson.com/apis/mobile-java-push/

이것을 직접 구현하면 까다로운 부분은 사용자가 보지 않고 들어오는 SMS를 삭제하는 것입니다. 아니면 그들이 당신의 경우에 그것을 볼 수 있습니다.

다음과 같이 작동합니다. BroadCastReceiver를 사용하여 SMS 삭제-Android

예, 이와 같은 코드를 작성하는 것은 위험 할 수 있으며 응용 프로그램에서 없어야 할 SMS를 삭제했기 때문에 누군가의 인생을 망칠 수 있습니다.


1
lol : "그렇습니다. 이와 같은 코드를 작성하는 것은 위험 할 수 있으며, 응용 프로그램에 없어야 할 SMS를 삭제했기 때문에 누군가의 인생을 망칠 수 있습니다." 그것을 위해 공감하십시오. lol.
Kumar Ravi

Mobile Java Push와의 연결이 끊어졌으며 서비스 자체는 더 이상 사용되지 않는 것 같습니다.
naXa

1

Google 클라우드 메시징 또는 GCM 을 사용할 수 있으며 무료이며 사용하기 쉽습니다. 또한 PushWoosh 와 같은 타사 푸시 서버를 사용하여 유연성을 높일 수 있습니다



1

Firebase 클라우드 메시징FCM ( )은 새로운 버전의 GCM입니다. FCM은 메시지를 안전하고 무료로 보낼 수있는 플랫폼 간 메시징 솔루션입니다. Android, iOS, Web (javascript), Unity 및 C ++에서 안정적으로 메시지를 전달하기 위해 GCM의 중앙 인프라를 상속합니다.

2018 년 4 월 10 일부로 Google은 GCM을 승인하지 않았습니다. GCM 서버 및 클라이언트 API는 더 이상 사용되지 않으며 2019 년 4 월 11 일에 제거 될 예정입니다. Google은 GCM 애플리케이션을 FCM (Firebase Cloud Messaging)으로 마이그레이션하는 것이 좋습니다.이 플랫폼은 안정적이고 확장 가능한 GCM 인프라를 상속합니다.

자원


0

푸셔 를 사용할 수 있습니다

웹 및 모바일 애플리케이션에 실시간 데이터 및 기능을 매우 쉽게 추가 할 수있는 호스팅 서비스입니다.
Pusher는 모든 주요 런타임 및 프레임 워크에 통합 할 수있는 라이브러리를 제공합니다.

PHP, Ruby, Python, Java, .NET, Go and Node
JavaScript, Objective-C (iOS) and Java (Android)클라이언트 의 서버 에서.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.