Android, wykrywaj uruchamianie innych aplikacji


92

Próbuję stworzyć aplikację, która uniemożliwia użytkownikowi uzyskanie dostępu do określonej aplikacji bez hasła. Scenariusz jest taki ...

  1. użytkownik klika aplikację „E-mail” (na przykład)
  2. moja aplikacja wykrywa uruchomienie aplikacji
  3. moja aplikacja potwierdza, że ​​jest to aplikacja „E-mail”
  4. moja aplikacja otwiera widok u góry, prosząc o podanie hasła
  5. użytkownik wprowadza hasło, jeśli jest prawidłowe, moja aplikacja znika, pozostawiając aplikację „E-mail” na górze

Resztę robię dobrze, tylko część 2 jest dla mnie zagadką, a po wielu dniach czytania w Broadcast Intents itp. I próbowaniu nasłuchiwania „android.intent.action.MAIN” itp. W moich próbnych projektach nie mogę wydaje się wykrywać, kiedy jest uruchomiona inna aplikacja niż moja.

Czy ktoś może pomóc? Czy podchodzę do tego we właściwy sposób, szukając nowych aplikacji nadających zamiar rozpoczęcia, czy też powinienem czytać dziennik systemowy w poszukiwaniu nowych intencji lub robić coś w kodzie natywnym?

Wszelkie wskazówki by pomogły, nawet jeśli nie możesz na nie odpowiedzieć w pełni, będę mógł przeprowadzić więcej badań. Wielkie dzięki. Ian


Nie jestem pewien, jak to zrobili, ale aplikacje takie jak App Protector robią dokładnie to, o co prosisz, więc jest to technicznie możliwe.
hanspeide

@lan, jak rozwiązałeś problem, podziel się swoją wiedzą
nida

cześć, czy masz rozwiązanie?
ask4solutions

Odpowiedzi:


34

Myślę, że możemy wykorzystać logcat i przeanalizować jego wynik.

We wszystkich podobnych programach znalazłem to uprawnienie:

android.permission.READ_LOGS

Oznacza to, że wszyscy go używają, ale wygląda na to, że program się uruchamia, a następnie nasz program (ochrona aplikacji) uruchomi się i przeniesie do przodu.

Użyj poniższego kodu:

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

I nie zapomnij dodać jego uprawnień w pliku Manifest.


proszę, gdzie mamy umieścić ten kod? w usłudze? w onStartCommand ()?
haythem souissi

56
nie będzie działać z JellyBean i nowszymi wersjami. Uprawnienie READ_LOGS jest teraz zarezerwowane tylko dla aplikacji systemowych.
Biegał

5
Czy jesteś tego absolutnie pewien? Ponieważ wydaje się, że Smart AppLock jest w stanie to zrobić nawet na urządzeniach JB. Czy to dlatego, że aplikacja podnosi się do statusu administratora urządzenia? play.google.com/store/apps/…
Karthik Balakrishnan

1
@Torcellite, ta aplikacja ma uprawnienie „Uruchom zadania”, więc może zamiast tego używać tej techniki.
Sam

1
@Ran, więc co zrobić, aby go teraz użyć ... czy jest już dostępne rozwiązanie, aby rozwiązać problem opisany w pytaniu, ponieważ muszę być ponad
żelkami

19

Efektywnym sposobem na zrobienie tego jest usługa z pętlą czasową, która sprawdza

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

Przeglądasz tę listę, aby sprawdzić, co jest uruchomione w telefonie. Teraz możesz je zidentyfikować za pomocą identyfikatorów i nazwy procesu, więc w przypadku standardowych działań jest to łatwe w przypadku niestandardowych, chyba że zatrzymasz je wszystkie, trudno je rozróżnić ...

Uwaga: to nie jest lista tego, co faktycznie jest na ekranie, tylko lista tego, co działa ... może trochę unieważnia twój cel, ale przynajmniej będziesz wiedział, kiedy coś zacznie działać ... będzie nadal w tym lista nawet w tle.

Jeśli chodzi o hasło, możesz po prostu rozpocząć swoją aktywność, gdy znajdziesz chronioną aplikację lub cokolwiek innego.


czy można uzyskać czas, w którym aplikacja została uruchomiona / wznowiona?
0LLiena

4
W systemie Android L android.app.usagezamiast tego użyj pakietu. developer.android.com/reference/android/app/usage/ ...
Plo_Koon

12

Myślę i mam nadzieję, że nie jest to możliwe. Zastanów się, jak łatwo taka funkcjonalność może zostać wykorzystana przez złośliwe oprogramowanie. Możesz słuchać intencji skierowanych do Ciebie i tych, które są transmitowane, ale uruchomienie aplikacji nie powinno być wydarzeniem transmitowanym.

To, co możesz zrobić, to wymienić program uruchamiający . Jeśli użytkownik wyrazi na to zgodę.


1
Dlaczego nie miałoby to być możliwe? To moje urządzenie i decyduję, co na nim uruchomić. Jak to stanowi większy problem niż inne uprawnienia, które rutynowo przyznajemy? Zastępczy program uruchamiający nie przechwyci uruchomienia wszystkich aplikacji, tylko tych uruchomionych bezpośrednio przez niego. Istnieje wiele komentarzy na ten temat i podobnych wątków w SO, które twierdzą, że możliwość prostego zobaczenia przemijających zamiarów byłaby dużym problemem, ale nikt nie wyjaśnia, na czym polega problem i dlaczego należy go uznać za tak nieprzyjemny, że istniejący system przywilejów nie może być wykorzystywane do wyjaśnienia użytkownikowi, co się dzieje.
Kevin Whitefoot

Ponieważ potencjalne uprawnienia idą, ten jest doozy. Celem posiadania modelu bezpieczeństwa jest umożliwienie większości legalnych przypadków użycia, przy jednoczesnym zapobieganiu większości (najlepiej wszystkim) exploitom. Ochrona wymaga nie tylko Ciebie (prawdopodobnie doświadczonego użytkownika), ale także naiwnych użytkowników instalujących aplikacje oraz twórców aplikacji, którzy nie muszą rozważać kolejnego wektora ataku. Całe bezpieczeństwo jest kompromisem: w tym przypadku między użytecznością a mocą a masową możliwością wykorzystania. Możesz sklonować stos Androida i zakodować własny system, jeśli naprawdę chcesz mieć taki stopień wolności dla siebie.
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();
    }
}

Możesz pobrać bieżące działanie Activityi sprawdzić, czy Activityodpowiada to Email aplikacji.

Uruchom CheckRunningActivity Threadprzy Applicationstarcie (lub przy starcie urządzenia).

new CheckRunningActivity().start();

Aktualizacja: ta klasa wymaga android.permission.GET_TASKSpozwolenia, więc dodaj następną linię do manifestu:

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

Używam tego podejścia, ale dzięki zapętleniu Twoje „// pokaż swoją aktywność tutaj, w górnej części PACKAGE_NAME.ACTIVITY_NAME”, będzie ponownie otwierane. Jakieś obejście tego problemu?
Anuj Sharma

zatrzymaj wątek CheckRunningActivity, gdy uzyskasz pożądany rezultat
Veaceslav Gaidarji

Dzięki za odpowiedź, to jak / kiedy ten wątek zostanie ponownie uruchomiony? Korzystam z usługi Sticky Service.
Anuj Sharma

zależy od kontekstu problemu, opisz szczegółowo, co chcesz otrzymać.
Veaceslav Gaidarji,

2
W twoim kodzie Looper.loop()instrukcja wygląda tak, jakby nigdy nie została wykonana, ponieważ while(true)pętla nigdy się nie kończy. Czy to pomyłka?
Sam

11

Głównym problemem jest to, że próbujesz nasłuchiwać ukrytych intencji, gdy program uruchamiający (ekran główny) zazwyczaj używa wyraźnych zamiarów.

Ukryta intencja ma miejsce, gdy chcesz powiedzieć „Ktoś odtworzy ten film”, a Android wybiera aplikację, która może obsłużyć ten cel.

To, co dzieje się po kliknięciu ikony „E-mail” na ekranie głównym, jest wyraźnym zamiarem. W szczególności mówi Androidowi, aby otworzył tę konkretną aplikację za pomocą w pełni kwalifikowanej nazwy (np. Com.android.mail lub coś w tym rodzaju).

Nie ma sposobu, aby AFAIK przechwycić takie wyraźne zamiary. Jest to środek bezpieczeństwa wbudowany w system Android, że żadne dwa działania nie mogą mieć tej samej w pełni kwalifikowanej nazwy pakietu. Zapobiega to klonowaniu aplikacji i podszywaniu się pod tę aplikację. Jeśli to, co chcesz zrobić, było możliwe, teoretycznie możesz zainstalować aplikację, która może zablokować działanie wszystkich aplikacji konkurencji.

To, co próbujesz zrobić, jest sprzeczne z modelem bezpieczeństwa Androida.

Jedną z rzeczy, które możesz zrobić, to nawiązać współpracę z konkretnymi twórcami aplikacji, aby przekazać intencje do swojego systemu bezpieczeństwa, ale prawdopodobnie nie jest to coś, z czym chcesz się zmierzyć.


6

getRunningTasks() jest przestarzałe w systemie Android L.

Aby uzyskać statystyki użytkowania aplikacji, możesz użyć klasy UsageStats z pakietu android.app.usage .

Nowy interfejs API statystyk użytkowania aplikacji umożliwia programistom aplikacji zbieranie statystyk związanych z używaniem aplikacji. Ten interfejs API zapewnia bardziej szczegółowe informacje o użyciu niż przestarzała metoda getRecentTasks ().

Aby korzystać z tego interfejsu API, musisz najpierw zadeklarować android.permission.PACKAGE_USAGE_STATSpozwolenie w swoim manifeście. Użytkownik musi również włączyć dostęp do tej aplikacji za pośrednictwem Settings > Security > Apps with usage access.

Oto podstawowy przykład aplikacji pokazujący, jak używać interfejsu API statystyk użycia aplikacji, aby umożliwić użytkownikom zbieranie statystyk związanych z używaniem aplikacji.


jak statystyki użytkowania mogą pomóc w ustaleniu, która aplikacja jest na pierwszym planie?
Ajay

3

Być może potrzebujesz usługi, czegoś, co będzie stale działać w tle. Niech twoja służba zrobi to, co powiedziałeś. Słuchaj android.intent.action.MAIN również w kategorii android.intent.category.LAUNCHER. Następnie niech ten odbiornik transmisji zastąpi metodę onReceive i sprawdź, czy jest nazwa aplikacji itp.


2
Brzmi to jak metoda, o której myślałem, ale mam problemy z odebraniem programu MAIN (cat. LAUNCHER) za pomocą podstawowego BroadcastReceiver. Czy ktoś wcześniej to zrobił? Na tym etapie chcę tylko wykryć, że aplikacja została uruchomiona lub wznowiona. Mogę wtedy porównać nazwę pakietu do ciągu zawierającego nazwy, których szukam.
Ian
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.