android - programacion - Iniciar la aplicación solo si no está funcionando actualmente
manual de programacion android pdf (11)
En lugar de mostrar la actividad de Splash al hacer clic en la notificación, muestre su MainActivity porque su actividad de splash se cerrará después de un tiempo, pero MainActivity permanecerá abierta y
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
Estoy enviando una notificación de inserción a los usuarios, que al hacer clic en ella abre la aplicación.
Mi problema es que cuando la aplicación ya está abierta, haga clic en la notificación para volver a iniciarla.
Solo quiero que inicie la aplicación si aún no se está ejecutando.
Estoy usando la intención pendiente en la notificación:
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, Splash.class), 0);
Vi mensajes que dicen usar:
<activity
android:name=".Splash"
android:launchMode="singleTask"
pero la cosa es que mi aplicación en ejecución está ejecutando otra actividad, luego el splash que se termina después de 7 segundos desde el inicio de la aplicación, por lo que cuando la aplicación se ejecuta, Splash no es la actividad actual
En primer lugar, establezca una tarea predeterminada de android:taskAffinity="com.example.testp.yourPreferredName"
en su elemento de Application
en el archivo Manifest. Mantenga su android:launchMode="singleTask"
en su SplashActivity
. Ahora, ya que su SplashActivity es su entrada principal, agregue este código a onResume()
, onNewIntent()
y onCreate()
(por un segundo pensamiento, no se recomienda onResume ()) - siga los comentarios en el código
//Note these following lines of code will work like magic only if its UPVOTED.
//so upvote before you try it.-or it will crash with SecurityException
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1000);
for(int i =0; i< taskInfo.size(); i++){
String PackageName = taskInfo.get(i).baseActivity.getPackageName();
if(PackageName.equals("packagename.appname")){// suppose .answerer.Elltz
//if the current runing actiivity is not the splash activity. it will be 1
//only if this is the first time your <taskAffinity> is be called as a task
if(taskInfo.get(i).numActivities >1){
//other activities are running, so kill this splash dead!! reload!!
finish();
// i am dying in onCreate..(the user didnt see nothing, that''s the good part)
//about this code. its a silent assassin
}
//Operation kill the Splash is done so retreat to base.
break;
}
}
Este código no funcionará en api 21+
; para que funcione, necesita usar AppTask , esto le ahorrará líneas de código adicionales ya que no estará en un Loop para encontrar su Task
.
Espero eso ayude
Para aquellos que usan Xamarin.Android . La versión de Xamarin de la respuesta de David Wasser está abajo:
//Create notification
var notificationManager = GetSystemService(Context.NotificationService) as NotificationManager;
Intent uiIntent = PackageManager.GetLaunchIntentForPackage("com.company.app");
//Create the notification
var notification = new Notification(Android.Resource.Drawable.SymActionEmail, title);
//Auto-cancel will remove the notification once the user touches it
notification.Flags = NotificationFlags.AutoCancel;
//Set the notification info
//we use the pending intent, passing our ui intent over, which will get called
//when the notification is tapped.
notification.SetLatestEventInfo(this, title, desc, PendingIntent.GetActivity(this, 0, uiIntent, PendingIntentFlags.OneShot));
//Show the notification
notificationManager.Notify(0, notification);
Puede utilizar una emisión ordenada para lograr esto.
1) Cambie su PendingIntent
para iniciar un BroadcastReceiver
que decidirá si iniciar la actividad o no hacer nada:
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, DecisionReceiver.class), 0);
2) Crear la decisión BroadcastReceiver
:
public class DecisionReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
context.sendOrderedBroadcast(new Intent(MainActivity.NOTIFICATION_ACTION), null, new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (getResultCode() == MainActivity.IS_ALIVE) {
// Activity is in the foreground
}
else {
// Activity is not in the foreground
}
}
}, null, 0, null, null);
}
}
3) Cree un BroadcastReceiver
en su actividad que indique que está vivo:
public static final String NOTIFICATION_ACTION = "com.mypackage.myapplication.NOTIFICATION";
public static final int IS_ALIVE = 1;
private BroadcastReceiver mAliveReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
setResultCode(IS_ALIVE);
}
};
// Register onResume, unregister onPause
// Essentially receiver only responds if the activity is the foreground activity
@Override
protected void onResume() {
super.onResume();
registerReceiver(mAliveReceiver, new IntentFilter(NOTIFICATION_ACTION));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mAliveReceiver);
}
Usa Splash como Fragmento en lugar de Actividad. Mantenga el fragmento de Splash (7 segundos), reemplace el mismo con el deseado (página de destino).
Agregue launchMode = "singleTask" al manifiesto.
Como ya lo dijo Rahul , onNewIntent()
se llama si la aplicación ya se está ejecutando else onCreate()
@Override
protected void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
}
O
Ve con la respuesta de David , parece prometedor.
Use un " Intent
lanzamiento" para su aplicación, como este:
PackageManager pm = getPackageManager();
Intent launchIntent = pm.getLaunchIntentForPackage("your.package.name");
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, launchIntent, 0);
Reemplace "your.package.name" con el nombre de su paquete del manifiesto de Android.
Además, debes eliminar el launchMode="singleTask"
de tu manifiesto. El comportamiento estándar de Android hará lo que quieras.
cuando se hace clic en la notificación y su código que redirige a su pantalla deseada simplemente reemplace ese código llamando a este método y redireccione a una pantalla en particular sobre la base de resultados "verdadero / falso".
private boolean isAppOnForeground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
final String packageName = context.getPackageName();
for (RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}
intente agregar esto a su intención de llevar la actividad al frente si se ejecuta en segundo plano
Intent intent = new Intent(this, Splash.class); intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
notificationIntent.addFlags (Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
notificationIntent.putExtras(bundle);
PendingIntent pintent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
Y tal vez no inicie la Actividad de Splash y vuelva a abrir (traiga al frente) MainActivity y actualice la interfaz de usuario con un oyente que le indique que tiene una nueva notificación (con una bandera - boolean o con una Interfaz para hacer un oyente) .
String appPackageName = "";
private void isApplicationInForeground() throws Exception {
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
final List<ActivityManager.RunningAppProcessInfo> processInfos = am
.getRunningAppProcesses();
ActivityManager.RunningAppProcessInfo processInfo = processInfos
.get(0);
// for (ActivityManager.RunningAppProcessInfo processInfo : processInfos) {
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
// getting process at 0th index means our application is on top on all apps or currently open
appPackageName = (Arrays.asList(processInfo.pkgList).get(0));
}
// }
}
else {
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
ComponentName componentInfo = null;
componentInfo = taskInfo.get(0).topActivity;
appPackageName = componentInfo.getPackageName();
}
}
private void notifyMessage(String text) {
if (appPackageName.contains("com.example.test")) {
// do not notify
}
else {
// create notification and notify user
}
}