Cześć,
Proszę o wytłumaczenie i porady odnośnie Android background services & notifications.
Jak to dokładnie działa z czym to się je itp.
Chcę w swojej aplikacji zrobić powiadomienia takie jak na facebooku czy instagramie. Mam tu na myśli to, że w momencie gdy teoretycznie mamy zamknięte aplikacje to one i tak działają w tle i sprawdzają czy nie ma nic nowego.. W momencie gdy pojawi się coś nowego w bazie to one wyświetlają powiadomienia.. np. Czy ta informacja była dla Ciebie przydatna [TAK] | [NIE].
Potrafię zrobić nowy 'service', zarejestrować go, uruchomić, zatrzymać... będzie on działał w tle. Nawet po zabiciu aplikacji serwis wystartuje i będzie działał od nowa ale... Jak teraz połączyć to z powiadomieniami i żeby te powiadomienia pokazywały się na androidach poniżej 6.0 i powyżej 6.0.
W android manifest dodane pozwolenia:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" tools:ignore="ProtectedPermissions"></uses-permission>
+ service zarejestrowany (przez zamknięciem tagu <application>):
<service
android:name=".BackgroundWorker"
android:exported="false"
android:process=":BackgroundAppServices"
android:stopWithTask="false" />
Po zalogowaniu użytkownika uruchamiam serwis:
Intent intent = new Intent(getApplicationContext(), BackgroundWorker.class);
startService(intent);
Sam BackgroundWorker.class wygląda następująco:
package pakietmojejaplikacji;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.media.RingtoneManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.facebook.AccessToken;
import com.facebook.CallbackManager;
import com.facebook.FacebookSdk;
import com.facebook.login.widget.LoginButton;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static pakietmojejaplikacji.App.CHANNEL_ID;
/**
* Created by Radosław on 10.01.2019.
*/
public class BackgroundWorker extends Service {
private static String FacbookDataUserId = null;
private static MediaPlayer mediaPlayer;
private Toast toast;
private Timer timer;
private TimerTask timerTask;
public View view;
public SharedPreferences preferences;
private SharedPreferences SessionFacebookLogedUser;
private String FacebookDataFromLoggedUserSession;
private static ConnectivityManager connectivityManager;
private class MyTimerTask extends TimerTask {
@Override
public void run() {
final RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
StringRequest postRequest = new StringRequest(Request.Method.POST, "https://adresmojegoapi/api/user.notiffication.get",
new Response.Listener<String>()
{
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onResponse(String response) {
Log.d("DANE_P" , response);
//showToast("Działam działam, nie śpie *****! { response: "+ response +" }");
try {
JSONObject powiadomienieObj = new JSONObject(response);
JSONObject powiadomienieObjJSONArray = powiadomienieObj.getJSONObject("powiadomienie");
/*
Tutaj z danymi robie co chcę i wyświetlam powiadomienie.
*/
ShowMyNotification(view, id_powiadomienia, imie, nazwsko);
//Not(id_powiadomienia, imie, nazwsko);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
//Toast.makeText(getApplicationContext(), "Coś sie wyjebało i nie działo hehe", Toast.LENGTH_LONG).show();
}
}
},
new Response.ErrorListener()
{
@Override
public void onErrorResponse(VolleyError error) {
}
}
) {
@Override
protected Map<String, String> getParams()
{
Map<String, String> params = new HashMap<String, String>();
params.put("facebook_id", FacbookDataUserId);
return params;
}
};
queue.add(postRequest);
}
}
private void showToast(String text) {
toast.setText(text);
toast.show();
}
@Override
public void onTaskRemoved(Intent rootIntent) {
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage(getPackageName());
super.onTaskRemoved(rootIntent);
}
@Override
public void onCreate() {
super.onCreate();
FacebookSdk.sdkInitialize(getApplicationContext());
connectivityManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
timer = new Timer();
}
@SuppressLint("WrongConstant")
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
clearTimerSchedule();
initTask();
timer.scheduleAtFixedRate(timerTask, 8 * 1000, 8 * 1000);
String command = intent.getStringExtra("close_notif");
}
private void clearTimerSchedule() {
if(timerTask != null) {
timerTask.cancel();
timer.purge();
}
}
private void initTask() {
timerTask = new BackgroundWorker.MyTimerTask();
}
@Override
public void onDestroy() {
showToast("ZABITO MNIE I NIE BEDE DZIAŁAŁ ");
clearTimerSchedule();
super.onDestroy();
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
public static void playMusic(Context context, int id)
{
mediaPlayer = MediaPlayer.create(context, id);
mediaPlayer.setLooping(false);
mediaPlayer.start();
}
public void Not(String IdPowiadomienia, String imie, String nazwsko){
Intent intentTak = new Intent(getApplicationContext(), Tak.class);
intentTak.putExtra("id_powiadomienia", Integer.valueOf(IdPowiadomienia));
PendingIntent pendingIntentTak = PendingIntent.getActivity(this, 1, intentTak, PendingIntent.FLAG_UPDATE_CURRENT);
Intent intentNie = new Intent(getApplicationContext(), MainActivity.class);
intentNie.putExtra("id_powiadomienia", Integer.valueOf(IdPowiadomienia));
PendingIntent pendingIntentNie = PendingIntent.getActivity(this, 0, intentNie, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle(imie + " xxxxxxxxxxxx")
.setContentText("yyyyyyyyyyyyyyy")
.setSmallIcon(R.drawable.iconx)
.addAction(R.drawable.icony, "TAK", pendingIntentTak)
.addAction(R.drawable.iconxzz, "NIE", pendingIntentNie)
.build();
final MediaPlayer mp = MediaPlayer.create(this, R.raw.powiadomienie);
mp.start();
startForeground(1, notification);
}
public void ShowMyNotification(View view, String IdPowiadomienia, String imie, String nazwsko) {
//Toast.makeText(getApplicationContext(), String.valueOf(IdPowiadomienia), Toast.LENGTH_SHORT).show();
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
Intent intentTak = new Intent(getApplicationContext(), Tak.class);
intentTak.putExtra("id_powiadomienia", Integer.valueOf(IdPowiadomienia));
PendingIntent pendingIntentTak = PendingIntent.getActivity(this, 1, intentTak, PendingIntent.FLAG_UPDATE_CURRENT);
Intent intentNie = new Intent(getApplicationContext(), MainActivity.class);
intentNie.putExtra("id_powiadomienia", Integer.valueOf(IdPowiadomienia));
PendingIntent pendingIntentNie = PendingIntent.getActivity(this, 0, intentNie, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setSmallIcon(R.drawable.ost_icon);
mBuilder.setContentTitle(imie + " xxxxxxxx ");
mBuilder.setContentText("yyyyyyyyy");
mBuilder.setPriority(IMPORTANCE_HIGH);
mBuilder.setSound(soundUri);
mBuilder.addAction(R.drawable.iconx, "TAK", pendingIntentTak);
mBuilder.addAction(R.drawable.icony, "NIE", pendingIntentNie);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, mBuilder.build());
}
}
Kombinowałem już na prawo i lewo ale nic sensownego (zgodnego ze "sztuką") nie udało mi się zrobić. Czy znajdzie się tutaj jakiś specjalista i pomoże mi z tym? Chcę tą funkcjonalność zrobić tak jak powinno być to zrobione.
Na kilku urządzeniach serwis po zabiciu aplikacji działa na innych nie.. Z powiadomieniami też jest różnie...
Koledzy bardziej doświadczeni ode mnie. Proszę was o pomoc. Bardzo będę wdzięczny za konkretne case'y.
Z góry dziękuję i pozdrawiam.