Встраиваем локальные уведомления

в 12:33, , рубрики: push notifications, push-уведомления, Блог компании FreeAmp, Разработка под android

Что самое ужасное в случае удаления приложения? Правильно, потеря связи с аудиторией и невозможность проинформировать о том, что у приложения сменился адрес прописки и имя пакета. Задачу решают Push уведомления, но это довольно хлопотно и не всегда удобно. А иногда и дорого.

Встраиваем локальные уведомления

Поэтому мы напишем свои, простые как барабан и надежные как танк — локальные push уведомления. Код получился универсальным, и впринципе, его можно использовать как альтернативу обычным «пушам», например для новостной рассылки о том, что вышла новая версия приложения или для клянчанья рейтинга, да для чего угодно.

Начнем с конфига. Это обычный текстовый файл в json-формате.

{
    "notifications":
        [
        {
            "id": 1 ,
            "title": "Sorry we are deleted from GPlay" ,
            "text": "Please click for download new app" ,
            "version": 105 ,
            "action": "market://search?q=freemp" ,
            "locale": "ru_Ru"
        }
        ] 
} 

где
— id: unique number of message
— title: title of message
— text: text of message
— version: if not set message for all (optional)
— action: default action (optional)
— locale: optional

Данный файл размещаем, например на гитхабе и добавляем на него ссылку:

public static final String MESSAGEURL = «github.com/recoilme/freemp/blob/master/message.json?raw=true»;

Затем где нибудь в районе onCreate основного активити вызываем:
new UpdateUtils(activity);

Готово. С настройкой покончено. Теперь как это работает.

При старте приложение чекает массив уведомлений и показывает следующее сообщение из тех, что не были показаны ранее.
При последующем старте — показывает следующее и так, пока уведомления не кончатся. Таким образом можно организовывать очередь сообщений. Я не знаю пока точно зачем, но наверняка пригодится.

Существуют два вида фильтров:
version — если задать, например 105 — то будет показываться только в 105 версии приложения. Можно, например, написать для пользователей версии 105, что вышла версия 106)
locale — локаль текста, если например необходимо сделать сообщение на русском, для русскоязычных пользователей

Параметр action — опциональный, это Uri, который будет вызван при клике на уведомлении. Можно, например, направить в маркет ну или в другое активити (в том числе свое).

Собственно это все. Довольно просто, ив то же время позволит нивелировать ущерб от возможного удаления. Ну или наладить диалог с пользователями.

Код, в действии можно посмотреть тут: https://github.com/recoilme/freemp
Но собственно пока это один файл. Возможно библиотека будет развиваться, добавлю возможность скачивания обновления или что то вроде того. Пока же код комфортно поместится и тут:

package org.freemp.android;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.text.TextUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Locale;

/**
 * Created by recoil on 06.08.14.
 * example file:

 {
 "notifications": [{ id":1, "title":"Sorry we are deleted from GPlay", "text":"Please click for download new app",
 "version":105 , "action":"market://search?q=freemp", "locale":"ru_Ru"}]
 }

  - id: unique number of message
  - title: title of message
  - text: text of message
  - version: if not set message for all (may be not set)
  - action: default action (may be not set)
  - locale: may be not set

 */

public class UpdateUtils {

    public static final String MESSAGEURL = "https://github.com/recoilme/freemp/blob/master/message.json?raw=true";
    private Context context;
    private Activity activity;
    private int versionCode;
    private String locale;

    public UpdateUtils(Activity activity) {
        this.activity = activity;
        context = activity.getApplicationContext();
        new Update().execute();
    }

    private class Update extends AsyncTask<Void,Void,String> {

        @Override
        protected String doInBackground(Void... params) {
            try {
                versionCode = context.getPackageManager()
                        .getPackageInfo(context.getPackageName(), 0).versionCode;
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
            locale = Locale.getDefault().toString();
            String response = "";
            DefaultHttpClient client = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(MESSAGEURL);
            try {
                HttpResponse httpResponse = client.execute(httpGet);
                InputStream content = httpResponse.getEntity().getContent();
                BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
                String s = "";
                while ((s = buffer.readLine()) != null) {
                    response += s;
                }
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            return response;
        }

        @Override
        protected void onPostExecute(String result) {
            if (!TextUtils.equals("",result)) {
                JSONObject jsonResult = null;
                try {
                    jsonResult = new JSONObject(result);
                }
                catch (JSONException e) {
                    e.printStackTrace();
                    return;
                }
                //process notifications if exists
                JSONArray notifications = jsonResult.optJSONArray("notifications");
                if (notifications==null) {
                    return;
                }

                if (context==null) {
                    return;
                }
                //string with showed messages
                String showedMessages = PreferenceManager.getDefaultSharedPreferences(context).getString(MESSAGEURL,"");
                for (int i=0;i<notifications.length();i++) {
                    JSONObject jsonNotification = notifications.optJSONObject(i);

                    if (jsonNotification==null) break;

                    final int version = jsonNotification.optInt("version",-1);
                    if (version>0 && version!=versionCode) {
                        continue;
                    }

                    final String localeTarget = jsonNotification.optString("locale","all");
                    if (!TextUtils.equals("all",localeTarget) && !TextUtils.equals(localeTarget,locale)) {
                        continue;
                    }

                    final int id = jsonNotification.optInt("id");
                    if (showedMessages.contains(id+";")) {
                        continue;
                    }
                    else {
                        showedMessages+=id+";";
                        PreferenceManager.getDefaultSharedPreferences(context).edit().putString(MESSAGEURL,showedMessages).commit();

                        Intent intent = null;
                        if (!TextUtils.equals("",jsonNotification.optString("action",""))) {
                            // if has action add it
                            intent = new Intent(Intent.ACTION_VIEW, Uri.parse(
                                    jsonNotification.optString("action","")));
                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                        }
                        else {
                            // if no - just inform
                            intent = new Intent(activity,activity.getClass());
                        }
                        PendingIntent pIntent = PendingIntent.getActivity(context, id, intent, 0);

                        // if you don't use support library, change NotificationCompat on Notification
                        Notification noti = new NotificationCompat.Builder(context)
                                .setContentTitle(jsonNotification.optString("title",""))
                                .setContentText(jsonNotification.optString("text",""))
                                .setSmallIcon(R.drawable.icon)//change this on your icon
                                .setContentIntent(pIntent).build();
                        NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
                        // hide the notification after its selected
                        noti.flags |= Notification.FLAG_AUTO_CANCEL;

                        notificationManager.notify(id, noti);
                        break;
                    }
                }

            }
        }

    }
}

Буду рад если никому не пригодится использовать ее в тех целях, для которых она создавалась)

Автор: recompileme

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js