studio programacion para móviles libro edición desarrollo desarrollar curso aprende aplicaciones android

programacion - ¿Cómo obtener el contexto actual de actividad en primer plano en android?



manual de programacion android pdf (11)

Cada vez que se ejecuta mi transmisión, quiero mostrar alerta a la actividad de primer plano.


( Nota: se agregó una API oficial en la API 14: ver esta respuesta https://.com/a/29786451/119733 )

NO UTILICE LA RESPUESTA ANTERIOR (waqas716).

Tendrá un problema de pérdida de memoria debido a la referencia estática a la actividad. Para obtener más detalles, consulte el siguiente enlace http://android-developers.blogspot.fr/2009/01/avoiding-memory-leaks.html

Para evitar esto, debe administrar las referencias de actividades. Agregue el nombre de la aplicación en el archivo de manifiesto:

<application android:name=".MyApp" .... </application>

Su clase de aplicación:

public class MyApp extends Application { public void onCreate() { super.onCreate(); } private Activity mCurrentActivity = null; public Activity getCurrentActivity(){ return mCurrentActivity; } public void setCurrentActivity(Activity mCurrentActivity){ this.mCurrentActivity = mCurrentActivity; } }

Crea una nueva actividad:

public class MyBaseActivity extends Activity { protected MyApp mMyApp; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mMyApp = (MyApp)this.getApplicationContext(); } protected void onResume() { super.onResume(); mMyApp.setCurrentActivity(this); } protected void onPause() { clearReferences(); super.onPause(); } protected void onDestroy() { clearReferences(); super.onDestroy(); } private void clearReferences(){ Activity currActivity = mMyApp.getCurrentActivity(); if (this.equals(currActivity)) mMyApp.setCurrentActivity(null); } }

Entonces, ahora, en lugar de extender la clase de actividad para sus actividades, solo extienda MyBaseActivity. Ahora puedes obtener tu actividad actual desde la aplicación o el contexto de la actividad de esa manera:

Activity currentActivity = ((MyApp)context.getApplicationContext()).getCurrentActivity();


Amplío en la parte superior de la respuesta de @ gezdy.

En cada actividad, en lugar de tener que "registrarse" en la Application con codificación manual, podemos utilizar la siguiente API desde el nivel 14, para ayudarnos a lograr un propósito similar con menos codificación manual.

public void registerActivityLifecycleCallbacks (Application.ActivityLifecycleCallbacks callback)

http://developer.android.com/reference/android/app/Application.html#registerActivityLifecycleCallbacks%28android.app.Application.ActivityLifecycleCallbacks%29

En Application.ActivityLifecycleCallbacks , puede obtener qué Activity está "asociada" o "separada" a esta Application .

Sin embargo, esta técnica solo está disponible desde el nivel 14 de la API.


La respuesta de waqas716 es buena. Creé una solución para un caso específico que exige menos código y mantenimiento.

Encontré un trabajo específico al tener un método estático para obtener una vista de la actividad que sospecho que está en primer plano. Puede repetir todas las actividades y verificar si desea o obtener el nombre de la actividad de la respuesta de Martin

ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE); ComponentName cn = am.getRunningTasks(1).get(0).topActivity;

Luego verifico si la vista no es nula y obtengo el contexto a través de getContext ().

View v = SuspectedActivity.get_view(); if(v != null) { // an example for using this context for something not // permissible in global application context. v.getContext().startActivity(new Intent("rubberduck.com.activities.SomeOtherActivity")); }


No me gustan las otras respuestas. El ActivityManager no está destinado a ser utilizado para obtener la actividad actual. Súper clasificación y dependiendo de onDestroy también es frágil y no es el mejor diseño.

Honestamente, lo mejor que he logrado hasta ahora es simplemente mantener una enumeración en mi aplicación, que se establece cuando se crea una actividad.

Otra recomendación podría ser simplemente evitar el uso de múltiples actividades si es posible. Esto se puede hacer con el uso de fragmentos o en mi preferencia de vistas personalizadas.


No pude encontrar una solución con la que nuestro equipo estaría satisfecho, así que rodó la nuestra. Usamos ActivityLifecycleCallbacks para realizar un seguimiento de la actividad actual y luego exponerla a través de un servicio. Más detalles aquí: https://.com/a/38650587/10793


Sabiendo que ActivityManager administra Activity , para que podamos obtener información de ActivityManager . Obtenemos el primer plano actual ejecutando Activity por

ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE); ComponentName cn = am.getRunningTasks(1).get(0).topActivity;


Tengo 3 años de retraso, pero lo responderé de todos modos en caso de que alguien encuentre esto como yo.

Lo resolví simplemente usando esto:

if (getIntent().toString().contains("MainActivity")) { // Do stuff if the current activity is MainActivity }

Tenga en cuenta que "getIntent (). ToString ()" incluye muchos otros textos, como el nombre de su paquete y cualquier filtro de intención para su actividad. Técnicamente, estamos verificando el intento actual, no la actividad, pero el resultado es el mismo. Simplemente use, p. Ej., Log.d ("test", getIntent (). ToString ()); si quieres ver todo el texto Esta solución es un poco hacky pero es mucho más clara en su código y la funcionalidad es la misma.


Una solución bastante simple es crear una clase de administrador único, en la que pueda almacenar una referencia a una o más Actividades, o cualquier otra cosa a la que desee acceder a través de la aplicación.

Llame a UberManager.getInstance().setMainActivity( activity ); en la actividad principal onCreate.

Llame a UberManager.getInstance().getMainActivity(); en cualquier lugar de tu aplicación para recuperarlo. (Estoy usando esto para poder usar Toast a partir de un hilo que no sea UI).

Asegúrese de agregar una llamada a UberManager.getInstance().cleanup(); cuando tu aplicación está siendo destruida

import android.app.Activity; public class UberManager { private static UberManager instance = new UberManager(); private Activity mainActivity = null; private UberManager() { } public static UberManager getInstance() { return instance; } public void setMainActivity( Activity mainActivity ) { this.mainActivity = mainActivity; } public Activity getMainActivity() { return mainActivity; } public void cleanup() { mainActivity = null; } }


getCurrentActivity () también está en ReactContextBaseJavaModule.
(Dado que inicialmente se planteó esta pregunta, muchas aplicaciones de Android también tienen el componente ReactNative: aplicación híbrida).

class ReactContext en ReactNative tiene todo el conjunto de lógica para mantener mCurrentActivity que se devuelve en getCurrentActivity ().

Nota: Deseo que getCurrentActivity () se implemente en la clase de aplicación de Android.


@lockwobr Gracias por la actualización

Esto no funciona el 100% del tiempo en la versión 16 de la API. Si lees el código en github, la función "currentActivityThread" fue modificada en Kitkat, así que quiero decir la versión 19ish, tipo de versión api difícil de adaptar a las versiones en github .

Tener acceso a la Activity actual es muy útil. ¿No sería bueno tener un método estático getActivity que devuelva la actividad actual sin preguntas innecesarias?

La clase de Activity es muy útil. Da acceso al subproceso de interfaz de usuario de la aplicación, vistas, recursos y muchos más. Numerosos métodos requieren un Context , pero ¿cómo obtener el puntero? Aquí hay algunas maneras:

  • Rastreando el estado de la aplicación usando métodos de ciclo de vida anulados. Debe almacenar la Actividad actual en una variable estática y necesita acceder al código de todas las Actividades.
  • Rastreando el estado de la aplicación usando Instrumentación. Declare la instrumentación en el manifiesto, impleméntela y use sus métodos para rastrear los cambios de actividad. Pasar un puntero de actividad a los métodos y clases utilizados en sus actividades. Inyectar el puntero usando una de las bibliotecas de inyección de código. Todos estos enfoques son bastante inconvenientes ; Afortunadamente, hay una forma mucho más fácil de obtener la Actividad actual.
  • Parece que el sistema necesita acceso a todas las actividades sin los problemas mencionados anteriormente. Por lo tanto, lo más probable es que haya una manera de obtener Actividades utilizando solo llamadas estáticas. Pasé mucho tiempo investigando las fuentes de Android en grepcode.com, y encontré lo que estaba buscando. Hay una clase llamada ActivityThread . Esta clase tiene acceso a todas las actividades y, lo que es aún mejor, tiene un método estático para obtener el ActivityThread actual. Solo hay un pequeño problema: la lista de actividades tiene acceso al paquete.

Fácil de resolver usando la reflexión:

public static Activity getActivity() { Class activityThreadClass = Class.forName("android.app.ActivityThread"); Object activityThread = activityThreadClass.getMethod("currentActivityThread").invoke(null); Field activitiesField = activityThreadClass.getDeclaredField("mActivities"); activitiesField.setAccessible(true); Map<Object, Object> activities = (Map<Object, Object>) activitiesField.get(activityThread); if (activities == null) return null; for (Object activityRecord : activities.values()) { Class activityRecordClass = activityRecord.getClass(); Field pausedField = activityRecordClass.getDeclaredField("paused"); pausedField.setAccessible(true); if (!pausedField.getBoolean(activityRecord)) { Field activityField = activityRecordClass.getDeclaredField("activity"); activityField.setAccessible(true); Activity activity = (Activity) activityField.get(activityRecord); return activity; } } return null; }

Tal método se puede utilizar en cualquier lugar de la aplicación y es mucho más conveniente que todos los enfoques mencionados. Además, parece que no es tan inseguro como parece. No introduce nuevas fugas potenciales o punteros nulos.

El fragmento de código anterior carece de manejo de excepciones y supone ingenuamente que la primera actividad en ejecución es la que estamos buscando. Es posible que desee agregar algunas verificaciones adicionales.

Entrada en el blog


Actualización 2 : hay una API oficial agregada para esto, por favor use ActivityLifecycleCallbacks lugar.

ACTUALIZAR:

Como señaló @gezdy, y estoy agradecido por eso. establecer referencia a null también para la actividad actual, en lugar de actualizar en cada onResume establecerlo como nulo en cada Activity onDestroy para evitar problemas de pérdida de memoria.

Hace un tiempo necesitaba la misma funcionalidad y aquí está el método de cómo lo logré. En cada actividad, anula estos métodos de ciclo de vida.

@Override protected void onResume() { super.onResume(); appConstantsObj.setCurrentActivity(this); } @Override protected void onPause() { clearReferences(); super.onPause(); } @Override protected void onDestroy() { clearReferences(); super.onDestroy(); } private void clearReferences(){ Activity currActivity = appConstantsObj.getCurrentActivity(); if (this.equals(currActivity)) appConstantsObj.setCurrentActivity(null); }

Ahora, en tu clase de transmisión, puedes acceder a la actividad actual para mostrar una alerta sobre ella.