Android, rileva quando vengono avviate altre app


92

Sto cercando di sviluppare un'app che impedisca a un utente di accedere a un'app specificata senza una password. Lo scenario è ...

  1. l'utente fa clic sull'app "Email" (ad esempio)
  2. la mia app rileva l'avvio di un'app
  3. la mia app conferma che è l'app "Email"
  4. la mia app apre una vista in alto, chiedendo una password
  5. l'utente inserisce una password, se corretta, la mia app scompare, lasciando in alto l'app "Email"

Sto bene a fare il resto, solo la parte 2 mi lascia perplesso, e dopo molti giorni leggendo su Broadcast Intents ecc. E cercando di ascoltare "android.intent.action.MAIN" ecc. Nei miei progetti di prova non posso sembrano rilevare quando viene avviata un'app diversa dalla mia.

Qualcuno può aiutare? Sto procedendo nel modo giusto, alla ricerca di nuove app che trasmettono un intento per iniziare, o dovrei leggere il registro di sistema per nuovi intenti o fare qualcosa in codice nativo?

Qualsiasi suggerimento aiuterebbe, anche se non puoi rispondere completamente sarò in grado di fare qualche ricerca in più. Molte grazie. Ian


Non sono sicuro di come abbiano fatto, ma app come App Protector fa esattamente quello che stai chiedendo, quindi è davvero tecnicamente possibile.
hanspeide

@lan come hai risolto il tuo problema puoi condividere le tue conoscenze
nida

ciao hai la soluzione?
ask4solutions

Risposte:


34

Penso che possiamo usare logcat e analizzare il suo output.

In tutti i programmi simili ho trovato questa autorizzazione:

android.permission.READ_LOGS

Significa che tutti lo usano ma sembra che il programma si avvii e poi il nostro programma (app protector) inizierà e porterà in primo piano.

Usa il codice seguente:

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();
    }

E non dimenticare di aggiungere la sua autorizzazione nel file Manifest.


per favore, dove dobbiamo mettere questo codice? in un servizio? in onStartCommand ()?
haythem souissi

56
non funzionerà da JellyBean e versioni successive. L'autorizzazione READ_LOGS è ora riservata solo alle app di sistema.
Ha corso il

5
Ne sei assolutamente sicuro? Perché Smart AppLock sembra essere in grado di farlo anche sui dispositivi JB. È perché l'applicazione si eleva allo stato di amministratore del dispositivo? play.google.com/store/apps/…
Karthik Balakrishnan

1
@ Torcellite, quell'app ha l'autorizzazione "Ottieni attività in esecuzione", quindi potrebbe utilizzare quella tecnica.
Sam

1
@Ran, quindi cosa fare per usarlo ora ... c'è una soluzione disponibile ora per risolvere il problema indicato nella domanda poiché ho bisogno di essere sopra i fagioli di gelatina ... per favore dai il tuo feedback al più presto ...
Shreyan Mehta

19

Un modo ingannevole per farlo è avere un servizio con un loop temporizzato che controlla

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

Scorri l'elenco per vedere cosa sta funzionando sul telefono. Ora puoi identificarli con id e processName, quindi per l'attività standard questo è facile per quelli personalizzati, a meno che non li fermi del tutto, è difficile discriminare ...

Nota: questo non è un elenco di ciò che è effettivamente sullo schermo, solo un elenco di ciò che è in esecuzione ... un po 'annullando il tuo obiettivo forse ma almeno saprai quando qualcosa sta iniziando a funzionare ... continuerà a esserci elenco anche se in background.

Per quanto riguarda la password, puoi semplicemente iniziare la tua attività quando trovi un'app protetta o qualsiasi altra cosa.


è possibile ottenere l'ora in cui l'app è stata avviata / ripresa?
0LLiena

4
In Android L usa android.app.usageinvece il pacchetto. developer.android.com/reference/android/app/usage/…
Plo_Koon

12

Penso e spero che questo non sia possibile. Considera quanto facilmente tale funzionalità potrebbe essere utilizzata in modo improprio da software dannoso. Puoi ascoltare gli intenti diretti a te e quelli trasmessi, ma l'avvio dell'applicazione non dovrebbe essere un evento di trasmissione.

Quello che potresti essere in grado di fare è sostituire il programma di avvio . Se l'utente acconsente.


1
Perché non dovrebbe essere possibile? È il mio dispositivo e decido cosa eseguirci. In che modo questo è più un problema rispetto alle altre autorizzazioni che concediamo abitualmente? Un launcher sostitutivo non catturerà il lancio di tutte le app solo quelle lanciate direttamente da esso. Ci sono molti commenti su questo e altri thread simili su SO che affermano che essere in grado di vedere semplicemente gli intenti che passano sarebbe un grosso problema ma nessuno spiega quale sia il problema e perché dovrebbe essere considerato così brutto che il sistema esistente di privilegi non può essere utilizzato per rendere chiaro all'utente cosa sta succedendo.
Kevin Whitefoot

Per quanto riguarda i permessi potenziali, questo è un po 'doozy. Lo scopo di avere un modello di sicurezza è abilitare i casi d'uso più legittimi, prevenendo la maggior parte (idealmente tutti) gli exploit. Non sei solo tu (presumibilmente un utente esperto) che deve essere protetto, ma anche gli utenti ingenui che installano app e gli autori di app che sono risparmiati dal dover considerare un altro vettore di attacco. Tutta la sicurezza è un compromesso: in questo caso, tra utilità e potenza rispetto a una massiccia sfruttabilità. Sei libero di clonare lo stack Android e codificare il tuo sistema se vuoi davvero quel grado di libertà per te stesso.
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();
    }
}

È possibile ottenere il funzionamento corrente Activitye verificare se ciò Activitycorrisponde Email all'applicazione.

Eseguire CheckRunningActivity Threadsu Applicationdi partenza (o al boot del dispositivo).

new CheckRunningActivity().start();

Aggiornamento: questa classe richiede l' android.permission.GET_TASKSautorizzazione, quindi aggiungi la riga successiva al manifest:

<uses-permission android:name="android.permission.GET_TASKS" />

Sto usando questo approccio ma questo aprirà il tuo "// mostra la tua attività qui sopra PACKAGE_NAME.ACTIVITY_NAME" ancora e ancora a causa del loop. Qualche soluzione alternativa per questo?
Anuj Sharma

interrompere il thread CheckRunningActivity quando si ottiene il risultato desiderato
Veaceslav Gaidarji

Grazie per la risposta, allora come / quando questo thread viene riavviato di nuovo? Sto usando un servizio appiccicoso.
Anuj Sharma

dipende dal contesto del problema, descrivi più dettagliatamente cosa vuoi ottenere.
Veaceslav Gaidarji

2
Nel tuo codice qui, l' Looper.loop()istruzione sembra che non verrà mai eseguita perché il while(true)ciclo non finisce mai. È un errore?
Sam

11

Il problema principale è che stai cercando di ascoltare gli intenti impliciti quando il Launcher (schermata iniziale) utilizza in genere gli intenti espliciti.

Un intento implicito è quando vuoi dire "Qualcuno riproduce questo video" e Android sceglie un'app in grado di gestire tale intento.

Un intento esplicito è ciò che accade quando fai clic sull'icona "Email" nella schermata iniziale. Sta specificatamente dicendo ad Android di aprire quella specifica app con un nome completo (ad esempio com.android.mail o qualcosa del genere).

Non c'è modo, AFAIK, di intercettare tali intenzioni esplicite. È una misura di sicurezza incorporata in Android che non esistono due attività che possono avere lo stesso nome di pacchetto completo. Ciò impedisce a terzi di clonare l'app e mascherarsi come quell'app. Se ciò che desideri fare fosse possibile, potresti teoricamente installare un'app che potrebbe bloccare il funzionamento di tutte le app della concorrenza.

Quello che stai cercando di fare va contro il modello di sicurezza di Android.

Una cosa che potresti fare è collaborare con sviluppatori di app specifici per inoltrare gli intenti al tuo sistema di sicurezza, ma probabilmente non è qualcosa con cui vuoi occuparti.


7

getRunningTasks() è deprecato in Android L.

Per ottenere le statistiche sull'utilizzo delle app puoi usare la classe UsageStats da android.app.usage pacchetto .

La nuova API delle statistiche sull'utilizzo delle app consente agli sviluppatori di app di raccogliere statistiche relative all'utilizzo delle applicazioni. Questa API fornisce informazioni sull'utilizzo più dettagliate rispetto al metodo getRecentTasks () deprecato.

Per utilizzare questa API, devi prima dichiarare l' android.permission.PACKAGE_USAGE_STATSautorizzazione nel tuo manifest. L'utente deve anche abilitare l'accesso per questa app tramiteSettings > Security > Apps with usage access .

Di seguito è riportato un esempio di app di base che mostra come utilizzare l'API delle statistiche sull'utilizzo delle app per consentire agli utenti di raccogliere statistiche relative all'utilizzo delle applicazioni.


in che modo le statistiche sull'utilizzo possono aiutare a sapere quale app è in primo piano?
Ajay

3

Forse hai bisogno di un servizio, qualcosa che verrà eseguito costantemente in background. Allora lascia che il tuo servizio faccia quello che hai detto. Ascolta android.intent.action.MAIN anche con la categoria android.intent.category.LAUNCHER. Quindi fai in modo che il ricevitore di trasmissione sovrascriva il metodo onReceive e controlla per vedere il nome dell'applicazione, ecc.


2
Sembra proprio il metodo a cui stavo pensando, ma sto lottando per ricevere la trasmissione MAIN (cat. LAUNCHER) con un BroadcastReceiver di base. Qualcuno è riuscito a farlo prima? In questa fase sto solo cercando di rilevare che un'applicazione è stata avviata o ripresa. Posso quindi confrontare il nome del pacchetto con una stringa contenente il nome che sto cercando.
Ian
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.