Android, detecta cuando se inician otras aplicaciones

92

Estoy tratando de desarrollar una aplicación que evite que un usuario acceda a una aplicación específica sin una contraseña. El escenario es ...

  1. el usuario hace clic en la aplicación "Correo electrónico" (por ejemplo)
  2. mi aplicación detecta el inicio de una aplicación
  3. mi aplicación confirma que es la aplicación "Correo electrónico"
  4. mi aplicación abre una vista en la parte superior, solicitando una contraseña
  5. el usuario ingresa una contraseña, si es correcta, mi aplicación desaparece, dejando la aplicación "Correo electrónico" en la parte superior

Estoy bien haciendo el resto, solo la parte 2 me está desconcertando, y después de muchos días leyendo sobre Broadcast Intents, etc. y tratando de escuchar "android.intent.action.MAIN", etc. en mis proyectos de prueba, no puedo parece detectar cuando se inicia una aplicación distinta a la mía.

¿Alguien puede ayudar? ¿Lo estoy haciendo de la manera correcta, en la búsqueda de nuevas aplicaciones que transmitan una intención de inicio, o debería leer el registro del sistema en busca de nuevas intenciones o hacer algo en código nativo?

Cualquier sugerencia ayudaría, incluso si no puede responderla por completo, podré investigar un poco más. Muchas gracias. Ian

Ian
fuente
No estoy seguro de cómo lo han hecho, pero aplicaciones como App Protector hacen exactamente lo que estás pidiendo, por lo que es técnicamente posible.
Hanspeide
@lan cómo resolvió su problema, ¿puede compartir su conocimiento?
nida
hola tienes la solución?
ask4solutions

Respuestas:

34

Creo que podemos usar logcat y analizar su salida.

En todos los programas similares he encontrado este permiso:

android.permission.READ_LOGS

Significa que todos lo usan, pero parece que el programa se inicia y luego nuestro programa (protector de aplicaciones) se iniciará y se mostrará al frente.

Utilice el siguiente código:

try
    {
        Process mLogcatProc = null;
        BufferedReader reader = null;
        mLogcatProc = Runtime.getRuntime().exec(new String[]{"logcat", "-d"});

        reader = new BufferedReader(new InputStreamReader(mLogcatProc.getInputStream()));

        String line;
        final StringBuilder log = new StringBuilder();
        String separator = System.getProperty("line.separator"); 

        while ((line = reader.readLine()) != null)
        {
            log.append(line);
            log.append(separator);
        }
        String w = log.toString();
        Toast.makeText(getApplicationContext(),w, Toast.LENGTH_LONG).show();
    }
    catch (Exception e) 
    {
        Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
    }

Y no olvide agregar su permiso en el archivo de manifiesto.

M.Movaffagh
fuente
por favor, ¿dónde tenemos que poner este código? en un servicio? en el onStartCommand ()?
haythem souissi
56
no funcionará desde JellyBean y superior. El permiso READ_LOGS ahora está reservado solo para aplicaciones del sistema.
Se realizó el
5
¿Estás absolutamente seguro de esto? Porque Smart AppLock parece poder hacer esto incluso en dispositivos JB. ¿Es porque la aplicación se eleva al estado de Administrador de dispositivos? play.google.com/store/apps/…
Karthik Balakrishnan
1
@Torcellite, esa aplicación tiene el permiso "Obtener tareas en ejecución", por lo que podría estar usando esa técnica en su lugar.
Sam
1
@Ran, entonces, qué hacer para usarlo ahora ... ¿hay una solución disponible ahora para resolver el problema indicado en la pregunta, ya que necesito estar por encima de los caramelos de goma? ... Por favor, dé sus comentarios lo antes posible ...
Shreyan Mehta
19

Una forma ingeniosa de hacerlo es tener un servicio con un ciclo cronometrado que verifique

ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningAppProcessInfo = am.getRunningAppProcesses();

Revisa esa lista para ver qué se está ejecutando en el teléfono. Ahora puede identificarlos con ids y processName, por lo que para la actividad estándar esto es fácil para los personalizados, a menos que los detenga, es difícil discriminarlos ...

Nota: esta no es una lista de lo que está realmente en la pantalla, solo una lista de lo que se está ejecutando ... anulando un poco su objetivo tal vez, pero al menos sabrá cuándo algo está comenzando a ejecutarse ... seguirá estando en eso lista incluso cuando está en segundo plano.

Para el tema de la contraseña, puede comenzar su actividad cuando encuentre una aplicación que esté protegida o lo que sea.

Aimeric
fuente
¿Es posible obtener la hora en que se inició / reanudó la aplicación?
0LLiena
4
En Android L use android.app.usagepackage en su lugar. developer.android.com/reference/android/app/usage/…
Plo_Koon
12

Creo y espero que esto no sea posible. Considere la facilidad con la que el software malintencionado podría abusar de dicha funcionalidad. Puede escuchar las intenciones dirigidas a usted y las que se transmiten, pero el inicio de la aplicación no debe ser un evento de transmisión.

Lo que puede hacer es reemplazar el lanzador . Si el usuario lo acepta.

Pontus Gagge
fuente
1
¿Por qué no debería ser posible? Es mi dispositivo y decido qué ejecutar en él. ¿Cómo es esto más un problema que los otros permisos que otorgamos habitualmente? Un lanzador de reemplazo no capturará el lanzamiento de todas las aplicaciones, solo aquellas lanzadas directamente por él. Hay muchos comentarios sobre este y otros hilos similares en SO que afirman que poder simplemente ver pasar las intenciones sería un problema masivo, pero nadie explica cuál es el problema y por qué debería considerarse tan desagradable que el sistema de privilegios existente no puede. Se utilizará para dejar claro al usuario lo que está sucediendo.
Kevin Whitefoot
En cuanto a los posibles permisos, este es fantástico. El objetivo de tener un modelo de seguridad es habilitar la mayoría de los casos de uso legítimos, mientras se previenen la mayoría (idealmente todos) de las vulnerabilidades. No solo usted (presumiblemente un usuario informado) necesita estar protegido, sino también los usuarios ingenuos que instalan aplicaciones y los escritores de aplicaciones que no tienen que considerar otro vector de ataque. Toda seguridad son compensaciones: en este caso, entre servicios públicos y energía versus explotabilidad masiva. Eres libre de clonar la pila de Android y codificar tu propio sistema si realmente quieres ese grado de libertad para ti.
Pontus Gagge
12
class CheckRunningActivity extends Thread{
    ActivityManager am = null;
    Context context = null;

    public CheckRunningActivity(Context con){
        context = con;
        am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    }

    public void run(){
        Looper.prepare();

        while(true){
            // Return a list of the tasks that are currently running,
            // with the most recent being first and older ones after in order.
            // Taken 1 inside getRunningTasks method means want to take only
            // top activity from stack and forgot the olders.
            List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1);

            String currentRunningActivityName = taskInfo.get(0).topActivity.getClassName();

            if (currentRunningActivityName.equals("PACKAGE_NAME.ACTIVITY_NAME")) {
                // show your activity here on top of PACKAGE_NAME.ACTIVITY_NAME
            }
        }
        Looper.loop();
    }
}

Puede ponerse en funcionamiento Activityy comprobar si Activitycorresponde a la Email aplicación.

Ejecutar CheckRunningActivity Threadal Applicationiniciar (o al iniciar el dispositivo).

new CheckRunningActivity().start();

Actualización: esta clase necesita android.permission.GET_TASKSpermiso, así que agregue la siguiente línea al manifiesto:

<uses-permission android:name="android.permission.GET_TASKS" />
Veaceslav Gaidarji
fuente
Estoy usando este enfoque, pero esto abrirá su "// mostrar su actividad aquí en la parte superior de PACKAGE_NAME.ACTIVITY_NAME" una y otra vez debido al bucle. ¿Alguna solución para eso?
Anuj Sharma
detenga el hilo CheckRunningActivity cuando obtenga el resultado deseado
Veaceslav Gaidarji
Gracias por la respuesta, entonces, ¿cómo / cuándo se reinicia este hilo de nuevo? Estoy usando un Sticky Service.
Anuj Sharma
Depende del contexto del problema, describa con más detalles, por favor, qué desea obtener.
Veaceslav Gaidarji
2
En su código aquí, la Looper.loop()declaración parece que nunca se ejecutará debido a que el while(true)ciclo nunca termina. ¿Es esto un error?
Sam
11

El problema principal es que está tratando de escuchar intenciones implícitas cuando el Lanzador (pantalla de inicio) generalmente usa intenciones explícitas.

Una intención implícita es cuando quieres decir "Alguien reproduce este video" y Android elige una aplicación que puede manejar esa intención.

Una intención explícita es lo que sucede cuando hace clic en el icono "Correo electrónico" en la pantalla de inicio. Específicamente, le dice a Android que abra esa aplicación específica con un nombre completo (es decir, com.android.mail o algo así).

No hay forma de que AFAIK intercepte tales intenciones explícitas. Es una medida de seguridad integrada en Android que no hay dos actividades que tengan el mismo nombre de paquete completo. Esto evita que un tercero clone la aplicación y se haga pasar por esa aplicación. Si lo que desea hacer fuera posible, teóricamente podría instalar una aplicación que podría bloquear el funcionamiento de todas las aplicaciones de la competencia.

Lo que está intentando hacer va en contra del modelo de seguridad de Android.

Una cosa que podría hacer es asociarse con desarrolladores de aplicaciones específicos para reenviar las intenciones a su sistema de seguridad, pero probablemente no sea algo con lo que quiera lidiar.

CodeFusionMobile
fuente
7

getRunningTasks() está en desuso en Android L.

Para obtener estadísticas de uso de la aplicación, puede usar la clase UsageStats del paquete android.app.usage .

La nueva API de estadísticas de uso de aplicaciones permite a los desarrolladores de aplicaciones recopilar estadísticas relacionadas con el uso de las aplicaciones. Esta API proporciona información de uso más detallada que el método getRecentTasks () obsoleto.

Para utilizar esta API, primero debe declarar el android.permission.PACKAGE_USAGE_STATSpermiso en su manifiesto. El usuario también debe habilitar el acceso a esta aplicación a través de Settings > Security > Apps with usage access.

A continuación, se muestra un ejemplo de aplicación básica que muestra cómo utilizar la API de estadísticas de uso de la aplicación para permitir a los usuarios recopilar estadísticas relacionadas con el uso de las aplicaciones.

Plo_Koon
fuente
¿Cómo las estadísticas de uso pueden ayudar a saber qué aplicación está en primer plano?
Ajay
3

Quizás necesite un servicio, algo que se ejecute en segundo plano constantemente. Que su servicio haga lo que dijo. Escuche android.intent.action.MAIN también con la categoría android.intent.category.LAUNCHER. Luego, haga que ese receptor de transmisión anule el método onReceive y verifique el nombre de la aplicación, etc.

Jacob Malliet
fuente
2
Esto suena como el método en el que estaba pensando, pero estoy luchando para recibir la transmisión PRINCIPAL (lanzador de cat.) Con un receptor de transmisión básico. ¿Alguien ha logrado hacer esto antes? En esta etapa, solo estoy buscando detectar que una aplicación se ha iniciado o reanudado. Luego puedo comparar el nombre del paquete con una cadena que contiene el nombre (s) que estoy buscando.
Ian