Что самое ужасное в случае удаления приложения? Правильно, потеря связи с аудиторией и невозможность проинформировать о том, что у приложения сменился адрес прописки и имя пакета. Задачу решают 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