27

I'm new here and I've searched for questions to help me but I have no clear answers.

I need to make an application to block other applications on the phone. I've seen several on the market but I want to make one. is there any way of knowing when a user tries to open an application and bring forward an activity? (to put the password).

I tried with FileObserver, but only works with files and directories (obviously). Could I make a listener that captures the Intent of the other applications before starting?

I apologize for my english and I appreciate your help!

Moog
  • 10,193
  • 2
  • 40
  • 66
ngbl
  • 273
  • 1
  • 4
  • 5
  • That service that checks every second will drain your battery in a couple hours. Wouldn't it be better to make a launcher / home app? – Erdal Sep 12 '11 at 08:01
  • you're right! But it's not what I want. Thanks for your answer! – ngbl Sep 22 '11 at 16:28

3 Answers3

41

No you cannot know when another application is launched without some kind of hack. This is because application launches are not broadcasted.

What you can do is creating a service running on fixed intervals , say 1000 milliseconds, that checks what non system application is on front. Kill that app and from the service pop a password input box. If that password is correct relaunch that application

Here is some code sample

    timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {   
           List<RunningAppProcessInfo> appProcesses= activityManager.getRunningAppProcesses();
        for (RunningAppProcessInfo appProcess : appProcesses) {
            try {
            if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
            if (!lastFrontAppPkg.equals((String) appProcess.pkgList[0])) {
            apkInfo = ApkInfo.getInfoFromPackageName(appProcess.pkgList[0], mContext);
                if (apkInfo == null || (apkInfo.getP().applicationInfo.flags && ApplicationInfo.FLAG_SYSTEM) == 1) {
                  // System app                                             continue;
                        } else if (((apkInfo.getP().versionName == null)) || (apkInfo.getP().requestedPermissions == null)) {
                    //Application that comes preloaded with the device
                        continue;
                     } else {
                     lastFrontAppPkg = (String) appProcess.pkgList[0];
                     }
    //kill the app
    //Here do the pupop with password to launch the lastFrontAppPkg if the pass is correct
                         }
                      }
                   }
                 } catch (Exception e) {
                  //e.printStackTrace();
                }
               }                        
             }
           }, 0, 1000);

And here is the ApkInfo.getInfoFromPackageName()

    /**
 * Get the ApkInfo class of the packageName requested
 * 
 * @param pkgName
 *            packageName
 * @return ApkInfo class of the apk requested or null if package name
 *         doesn't exist
 * @see ApkInfo
 */
public static ApkInfo getInfoFromPackageName(String pkgName,
        Context mContext) {
    ApkInfo newInfo = new ApkInfo();
    try {
        PackageInfo p = mContext.getPackageManager().getPackageInfo(
                pkgName, PackageManager.GET_PERMISSIONS);

        newInfo.appname = p.applicationInfo.loadLabel(
                mContext.getPackageManager()).toString();
        newInfo.pname = p.packageName;
        newInfo.versionName = p.versionName;
        newInfo.versionCode = p.versionCode;
        newInfo.icon = p.applicationInfo.loadIcon(mContext
                .getPackageManager());
        newInfo.setP(p);
    } catch (NameNotFoundException e) {
        e.printStackTrace();
        return null;
    }
    return newInfo;
}
weakwire
  • 9,284
  • 8
  • 53
  • 78
  • Thanks Weakwire! this is really useful! I need some work to do what I want, but is the general idea! Thank you! – ngbl Sep 07 '11 at 21:16
  • 1
    This is incomplete approach as there is no working solution for "//kill the app". – Anuj Sharma Jul 18 '14 at 09:13
  • in order to kill another app, your app must be running in foreground. You can then kill the app with its package name. check out https://stackoverflow.com/questions/23927405/is-it-possible-to-close-apps-programatically-which-are-running-in-background-in – mmbrian Feb 13 '15 at 09:32
  • @weakwire ... thanks for this good answer . I would like to know another method to run the code repetitively other than Timer because Timer is destroyed by system after sometime I have checked that code many times . Thanks in advance. –  Mar 25 '16 at 12:11
9

there is a way to do so . you can know when a application is launched. you can use packagemanager class to get all the information about any installed and inbuld application . and use the below code to know whwn that application is launched

           @Override
    public void run() {  Log.i("test","detector run");
        try {
            Process process;
            process = Runtime.getRuntime().exec(ClearLogCatCommand);
            process = Runtime.getRuntime().exec(LogCatCommand);
            br = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            // Check if it matches the pattern
            while(((line=br.readLine()) != null) && !this.isInterrupted()){

                Log.d("Detector", "RUN"+line);

                // Ignore launchers
                if (line.contains("cat=[" + Intent.CATEGORY_HOME + "]")) continue;

                Matcher m = ActivityNamePattern.matcher(line);
                if (!m.find()) continue;
                if (m.groupCount()<2){
                    // Log.d("Detector", "Unknown problem while matching logcat output. Might be SDK version?");
                    continue;
                }

                if (mListener!=null) mListener.onActivityStarting(m.group(1), m.group(2));

                Log.i("Detector", "Found activity launching: " + m.group(1) + "  /   " + m.group(2));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
satya prakash
  • 238
  • 3
  • 13
  • I m trying to use this code but there is something i am doing wrong. Please can you provide more code to use it. thanks. screenshot: http://oi57.tinypic.com/28b8gmd.jpg – Amit Kumar Khare Feb 14 '14 at 13:25
  • @anuj sharma its work on jelly been and above..... i have tested it my code work perfectly in even android L – satya prakash Aug 22 '14 at 16:21
4

You can now use an AccessibilityService that allows you to find out which Activity is at the top.

In the AccessibilityService class:

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
        ComponentName componentName = new ComponentName(
                event.getPackageName().toString(),
                event.getClassName().toString()
        );

        ActivityInfo activityInfo = tryGetActivity(componentName);
        boolean isActivity = activityInfo != null;
        if (isActivity) {
            Log.i("CurrentActivity", componentName.flattenToShortString());
        }
    }
}

You will have to turn the Accessibility on in your phone's settings, which can be done by going to Settings > Accessibility > Services > Your App. There are also a couple of permissions you'll have to add in your Manifest. A lot of the information can be found in the Android Developers site: http://developer.android.com/reference/android/accessibilityservice/AccessibilityService.html

Hope this helps!

user3700215
  • 185
  • 2
  • 10