Android, Erkennen, wann andere Apps gestartet werden

92

Ich versuche, eine App zu entwickeln, die verhindert, dass ein Benutzer ohne Kennwort zu einer bestimmten App gelangt. Das Szenario ist ...

  1. Benutzer klickt auf "E-Mail" App (zum Beispiel)
  2. Meine App erkennt den Start einer App
  3. Meine App bestätigt, dass es sich um die "E-Mail" -App handelt
  4. Meine App öffnet eine Ansicht von oben und fragt nach einem Passwort
  5. Der Benutzer gibt ein Passwort ein. Wenn dies korrekt ist, verschwindet meine App und die App "E-Mail" bleibt oben

Ich mache den Rest in Ordnung, nur Teil 2 verwirrt mich und nach vielen Tagen, in denen ich mich über Broadcast Intents usw. informiert und versucht habe, in meinen Testprojekten auf "android.intent.action.MAIN" usw. zu hören, kann ich nicht scheinen zu erkennen, wann eine andere App als meine gestartet wird.

Kann jemand helfen? Gehe ich richtig vor, wenn ich nach neuen Apps suche, die eine Startabsicht senden, oder sollte ich das Systemprotokoll auf neue Absichten lesen oder etwas in nativem Code tun?

Alle Hinweise würden helfen, auch wenn Sie sie nicht vollständig beantworten können, kann ich weitere Nachforschungen anstellen. Vielen Dank. Ian

Ian
quelle
Ich bin mir nicht sicher, wie sie es gemacht haben, aber Apps wie App Protector machen genau das, wonach Sie fragen, also ist es tatsächlich technisch möglich.
Hanspeide
@lan, wie Sie Ihr Problem gelöst haben, können Sie bitte Ihr Wissen teilen
nida
Hallo, hast du die Lösung?
ask4solutions

Antworten:

34

Ich denke, wir können logcat die Ausgabe verwenden und analysieren.

In allen ähnlichen Programmen habe ich diese Berechtigung gefunden:

android.permission.READ_LOGS

Es bedeutet, dass alle es verwenden, aber es scheint, dass das Programm startet und danach unser Programm (App Protector) startet und nach vorne bringt.

Verwenden Sie den folgenden Code:

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

Und vergessen Sie nicht, die Berechtigung in die Manifest-Datei einzufügen.

M. Movaffagh
quelle
Bitte, wo müssen wir diesen Code setzen? in einem Dienst? im onStartCommand ()?
Haythem Souissi
56
funktioniert nicht mit JellyBean und höher. Die Berechtigung READ_LOGS ist jetzt nur für System-Apps reserviert.
Ran
5
Bist du dir da absolut sicher? Denn Smart AppLock scheint dies auch auf JB-Geräten zu können. Liegt es daran, dass sich die Anwendung in den Status eines Geräteadministrators erhebt? play.google.com/store/apps/…
Karthik Balakrishnan
1
@Torcellite, diese App verfügt über die Berechtigung "Laufende Aufgaben ausführen", sodass möglicherweise stattdessen diese Technik verwendet wird.
Sam
1
@Ran also was tun, um es jetzt zu verwenden ... gibt es jetzt eine Lösung, um das in der Frage angegebene Problem zu lösen, da ich über
Gummibärchen sein muss
19

Eine spielerische Möglichkeit, dies zu tun, besteht darin, einen Dienst mit einer Zeitschleife zu haben, die dies überprüft

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

Sie durchlaufen diese Liste, um zu sehen, was auf dem Telefon ausgeführt wird. Jetzt können Sie sie mit IDs und processName identifizieren. Für Standardaktivitäten ist dies für benutzerdefinierte Aktivitäten also einfach, es sei denn, Sie stoppen sie alle, es ist schwer zu unterscheiden ...

Hinweis: Dies ist keine Liste der Dinge, die tatsächlich auf dem Bildschirm angezeigt werden, sondern nur eine Liste der Dinge, die gerade ausgeführt werden. Vielleicht wird Ihr Ziel irgendwie zunichte gemacht, aber zumindest werden Sie wissen, wann etwas zu laufen beginnt Liste auch im Hintergrund.

Für das Passwort können Sie Ihre Aktivität einfach starten, wenn Sie eine App gefunden haben, die geschützt ist oder was auch immer.

Aimerisch
quelle
Ist es möglich, den Zeitpunkt zu ermitteln, zu dem die App gestartet / fortgesetzt wurde?
0LLiena
4
Verwenden Sie in Android L android.app.usagestattdessen das Paket. developer.android.com/reference/android/app/usage/…
Plo_Koon
12

Ich denke und hoffe, dass dies nicht möglich ist. Überlegen Sie, wie leicht solche Funktionen von schädlicher Software missbraucht werden können. Sie können sich die an Sie gerichteten und die gesendeten Absichten anhören, aber das Starten der Anwendung sollte kein Sendeereignis sein.

Möglicherweise können Sie den Launcher ersetzen . Wenn der Benutzer damit einverstanden ist.

Pontus Gagge
quelle
1
Warum sollte es nicht möglich sein? Es ist mein Gerät und ich entscheide, was darauf ausgeführt werden soll. Wie ist dies ein größeres Problem als die anderen Berechtigungen, die wir routinemäßig erteilen? Ein Ersatz-Launcher erfasst nicht alle Apps, sondern nur diejenigen, die direkt von ihm gestartet wurden. Es gibt viele Kommentare zu diesem und ähnlichen Themen zu SO, in denen behauptet wird, dass es ein massives Problem wäre, einfach zu sehen, wie Absichten vorübergehen, aber niemand erklärt, was das Problem ist und warum es als so böse angesehen werden sollte, dass das bestehende System von Privilegien dies nicht kann verwendet werden, um dem Benutzer klar zu machen, was passiert.
Kevin Whitefoot
Wenn es um zukünftige Berechtigungen geht, ist dies ein Trottel. Das Ziel eines Sicherheitsmodells besteht darin, die meisten legitimen Anwendungsfälle zu ermöglichen und gleichzeitig die meisten (im Idealfall alle) Exploits zu verhindern. Es sind nicht nur Sie (vermutlich ein sachkundiger Benutzer), die geschützt werden müssen, sondern auch naive Benutzer, die Apps installieren, und App-Autoren, denen es erspart bleibt, einen weiteren Angriffsvektor in Betracht zu ziehen. Alle Sicherheit ist ein Kompromiss: In diesem Fall zwischen Nutzen und Leistung im Vergleich zu massiver Ausnutzbarkeit. Sie können den Android-Stack klonen und Ihr eigenes System codieren, wenn Sie diesen Freiheitsgrad wirklich für sich selbst wünschen.
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();
    }
}

Sie können den aktuellen Status Activityaktivieren und prüfen, ob dies Activityder Email Anwendung entspricht.

Führen Sie CheckRunningActivity Threadauf ApplicationStart (oder auf dem Gerät boot).

new CheckRunningActivity().start();

Update: Diese Klasse benötigt eine android.permission.GET_TASKSBerechtigung. Fügen Sie daher die nächste Zeile zum Manifest hinzu:

<uses-permission android:name="android.permission.GET_TASKS" />
Veaceslav Gaidarji
quelle
Ich verwende diesen Ansatz, aber dies öffnet Ihr "// Zeigen Sie Ihre Aktivität hier oben auf PACKAGE_NAME.ACTIVITY_NAME" immer wieder wegen einer Schleife. Irgendeine Problemumgehung dafür?
Anuj Sharma
Stoppen Sie CheckRunningActivity Thread, wenn Sie das gewünschte Ergebnis erhalten
Veaceslav Gaidarji
Danke für die Antwort, wie / wann wird dieser Thread dann neu gestartet? Ich benutze einen Sticky Service.
Anuj Sharma
hängt vom Kontext des Problems ab, beschreiben Sie bitte genauer, was Sie erhalten möchten.
Veaceslav Gaidarji
2
In Ihrem Code hier Looper.loop()sieht die Anweisung so aus, als würde sie niemals ausgeführt, da die while(true)Schleife niemals beendet wird. Ist das ein Fehler?
Sam
11

Das Hauptproblem besteht darin, dass Sie versuchen, auf implizite Absichten zu achten, wenn der Launcher (Startbildschirm) normalerweise explizite Absichten verwendet.

Eine implizite Absicht ist, wenn Sie "Jemand spielt dieses Video ab" sagen möchten und Android eine App auswählt, die diese Absicht verarbeiten kann.

Eine explizite Absicht ist, was passiert, wenn Sie auf dem Startbildschirm auf das Symbol "E-Mail" klicken. Es weist Android ausdrücklich an, diese bestimmte App unter einem vollständig qualifizierten Namen (z. B. com.android.mail oder so) zu öffnen.

Es gibt keine Möglichkeit für AFAIK, solche expliziten Absichten abzufangen. Es ist eine in Android integrierte Sicherheitsmaßnahme, dass keine zwei Aktivitäten denselben vollständig qualifizierten Paketnamen haben können. Dies verhindert, dass Dritte die App klonen und sich als diese App tarnen. Wenn das, was Sie tun möchten, möglich wäre, könnten Sie theoretisch eine App installieren, die die Funktion aller Apps Ihrer Konkurrenz blockiert.

Was Sie versuchen, widerspricht dem Android-Sicherheitsmodell.

Eine Sache, die Sie tun können, ist, mit bestimmten App-Entwicklern zusammenzuarbeiten, um die Absichten an Ihr Sicherheitssystem weiterzuleiten, aber damit möchten Sie sich wahrscheinlich nicht befassen.

CodeFusionMobile
quelle
7

getRunningTasks() ist in Android L veraltet.

Um App-Nutzungsstatistiken zu erhalten, können Sie die UsageStats- Klasse aus dem android.app.usage- Paket verwenden.

Mit der neuen API für App-Nutzungsstatistiken können App-Entwickler Statistiken zur Nutzung der Anwendungen sammeln. Diese API bietet detailliertere Verwendungsinformationen als die veraltete Methode getRecentTasks ().

Um diese API verwenden zu können, müssen Sie zuerst die android.permission.PACKAGE_USAGE_STATSBerechtigung in Ihrem Manifest deklarieren . Der Benutzer muss auch den Zugriff für diese App über aktivieren Settings > Security > Apps with usage access.

Hier ist ein grundlegendes App-Beispiel, das zeigt, wie die App-Nutzungsstatistik-API verwendet wird, damit Benutzer Statistiken zur Nutzung der Anwendungen sammeln können.

Plo_Koon
quelle
Wie können Nutzungsstatistiken helfen, zu wissen, welche App im Vordergrund steht?
Ajay
3

Vielleicht brauchen Sie einen Dienst, der ständig im Hintergrund läuft. Dann lassen Sie Ihren Dienst tun, was Sie gesagt haben. Hören Sie auf die android.intent.action.MAIN auch mit der Kategorie android.intent.category.LAUNCHER. Lassen Sie dann diesen Broadcast-Empfänger die onReceive-Methode überschreiben und überprüfen Sie, ob der Name der Anwendung usw. angezeigt wird.

Jacob Malliet
quelle
2
Das klingt wie die Methode, über die ich nachgedacht habe, aber ich habe Probleme, die MAIN-Sendung (Kat. LAUNCHER) mit einem einfachen BroadcastReceiver zu empfangen. Hat das schon mal jemand geschafft? In diesem Stadium möchte ich nur feststellen, dass eine Anwendung gestartet oder wieder aufgenommen wurde. Ich kann dann den Paketnamen mit einer Zeichenfolge vergleichen, die die gesuchten Namen enthält.
Ian