Встраиваем локальные уведомления
Что самое ужасное в случае удаления приложения? Правильно, потеря связи с аудиторией и невозможность проинформировать о том, что у приложения сменился адрес прописки и имя пакета. Задачу решают 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
@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 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;
}
} }
} }
}
Буду рад если никому не пригодится использовать ее в тех целях, для которых она создавалась)