15

There are a class of Android applications that enable password protection on certain user-specified apps; for example, Android Protector. I need to approach this problem from a different direction.

Is it possible to create an application that blocks all activity launches unless they are on a predefined whitelist? Will there be unintended consequences with this approach? I am familiar with Android basics and have written a few reasonably simple apps, but I'm still trying to figure out how these "Protector" apps intercept the launch intents correctly. Would someone mind giving me a brief overview on the correct way to do this?

The basic problem is that we have a generic Android phone that needs to be locked down so that our clients (internal only) can access our custom applications without being able to play "Need for Speed", etc. I would like to remove the carrier bloatware, but rooting the device seems like it would be a maintenance headache. We want the setup for each phone to be as simple as installing a few custom applications.

rosco
  • 939
  • 9
  • 16
WorkerThread
  • 2,195
  • 2
  • 19
  • 23
  • 2
    I just want to add that this phone and associated applications will never be released to the public; it is internal only. If someone has an outside-the-box answer, I would appreciate that as well. – WorkerThread Mar 02 '11 at 15:00
  • 1
    Good question. I am curious myself. – Amir Raminfar Mar 02 '11 at 15:05
  • What about writing a custom launcher displaying only allowed applications? (You would need to lock Android Market too, because users could start installed apps from within the Market) – TomTasche Mar 02 '11 at 16:02
  • Thanks for the suggestion; I will investigate writing a custom launcher. Just thinking out loud here: what if some of our more tech savvy clients just add a shortcut to the home screen? Will that allow them to circumvent our lockdown? – WorkerThread Mar 02 '11 at 16:08

3 Answers3

7

Edited to elaborate on the solution

Overview

My simple solution was to add a new service and activity to my application. The service uses Handler and postDelayed to continuously schedule the monitoring task. The monitoring task checks that the current activity is on the whitelist. Getting the currently running activity involves ActivityManager and a call to getRunningTasks. After finishing the check, the monitoring task schedules itself to run again after X seconds (1, in my case).

If the activity on top is not on the whitelist, we launch the blocking activity which pops up over whatever is currently running. The key part of the blocking activity is that it overrides onBackPressed, preventing the user from simply going back to the "bad" activity. Pressing the Home key is the only way (to my knowledge) to leave this screen.

Tips

  • Build a backdoor into the lock screen. For example, my solution prompts for a password on a long-press of the back key. After entering the correct password, the monitor service goes to sleep for 5 minutes so I can do my administrative work
  • Display the name of the blocked activity
  • Gather a good whitelist before turning this on! Activities you should definitely whitelist: the launcher, package installer, your own app (obviously), the browser, if your app has a web-based component

I don't like that my service is constantly looping in the background; it seems wasteful. I'd like to find some way to be notified when a new task is being launched, but I couldn't find a way to do that. The battery usage for my particular value of the monitor period and my particular phone is acceptable; though you should definitely test before adopting this yourself.

WorkerThread
  • 2,195
  • 2
  • 19
  • 23
  • I'm interested in this approach. Would you mind posting code? Did you experience any problems with this technique? –  Jun 20 '11 at 20:01
  • @WorkerThread Very interesting! I'm really looking into it for our customers after we got $400 data bills this month :) Did you come up with better solution? Maybe some kind of system service to intercept launcher events? – katit Nov 12 '11 at 02:16
4

an efective solution,and here is the code from author's opinion

public class MonitorService extends Service {

private Handler handler;
Runnable runnable;

@Override
public void onCreate() {
    // TODO Auto-generated method stub
    super.onCreate();
    handler = new Handler();
    runnable = new Runnable() {
        @Override
        public void run() {
            new Thread(new Runnable() {
                @Override
                public void run() {

                    ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

                    List<ActivityManager.RunningTaskInfo> taskInfo = am
                            .getRunningTasks(1);

                    ComponentName componentInfo = taskInfo.get(0).topActivity;                      
                    String currentActivityName=componentInfo.getClassName();
                    String packageName=componentInfo.getPackageName();
                    if(whitelist.contains(currentActivityName)){

                        Intent launchIntent = new Intent();
                        launchIntent.setComponent(new ComponentName(blockActivityPackageName,
                                blockActivityName));
                        launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        startActivity(launchIntent);

                    }

                }
            }).start();
            handler.postDelayed(this, 1000);
        }
    };
    handler.postDelayed(runnable, 1000);
}

@Override
public void onStart(Intent intent, int startId) {
    super.onStart(intent, startId);
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onDestroy() {
    super.onDestroy();
    Intent intent = new Intent(this, MonitorService.class);
    startService(intent);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    return START_STICKY;
}
tkanzakic
  • 5,499
  • 16
  • 34
  • 41
vamdra
  • 41
  • 1
0

As you suggest, writing a custom launcher is probably would be cleaner; check out this open source launcher for reference http://code.google.com/p/adw-launcher-android/

Damian
  • 8,062
  • 4
  • 42
  • 43