跪求 “应用锁 / 程序锁 / 密码锁”的原理 本帖最后由 flying_vip_521 于 2011-09-07 13:50:41 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 您是想要root下的锁还是非root下的锁 是要隐藏用户图标还是要在用户启动某个程序的时候加密码? 应该是非root下的吧,如果应用“AAA”被保护的话,在启动“AAA”的时候,先呈现给用户的是密码验证界面,密码验证通过后解锁,如果通过home键或其他键访问到其他应用(如:lanch),则再启动该应用(AAA)的时候需要再次进行密码验证。 逻辑上应该是修改apk启动器或delvik虚拟机或ActivityManager或类似的东东,在调用onStart和onResume回调之前进行处理,类似于HOOK 可以试下设置intent-filter的优先级http://yangguangfu.iteye.com/blog/1063732 解决不了,坚决不让帖子沉,求高手指点:如何阻止点击应用的启动,直接进入密码验证界面(目前效果:应用主界面闪过后出现密码验证界面)service代码片段public String getTopPackage() { return ((ActivityManager.RunningTaskInfo) this.mActivityManager.getRunningTasks(1).get(0)).topActivity .getPackageName(); } public class ProtectorRunnable implements Runnable { @Override public void run() { Log.e(TAG, "--------run-------------"); Handler handler_ = ProtectorService.this.handler; Runnable runnable_ = ProtectorService.this.runnbale; String packageName = getTopPackage(); String className = getTopClass(); Log.e(TAG, "packageName=" + packageName + "----className=" + className); if (!packageName.equals(lastPkgName)) { MyApplication.appStatus.remove(lastPkgName); // Log.e(TAG, "appSt=atus"); } int id = mActivityManager.getRunningAppProcesses().get(0).pid; if (packageName.equals("com.android.settings") && !MyApplication.isPass(packageName)) { System.out.println(getTopIntent()); // mActivityManager.restartPackage(packageName);// 关闭应用,这样就保证了每次打开应用都是重新启动的一个实例 System.out.println("id="+id); android.os.Process.killProcess(id); Intent intent1 = new Intent(); intent1.setClass(ProtectorService.this, PasswordLock.class); intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); lastPkgName = ""; startActivity(intent1); } handler_.post(runnable_); } } 需求是什么,防止私人信息被偷看?看下activity的相关接口和生命周期,看能否在启动之前被截获 反编译过了,只是里边的代码比较乱,有些关键的地方,看不明白。目前的问题是,当我启动应用的时候,这个应用首先启动,主界面启动后,才弹出密码验证界面,体验太差,求解。service中启动一个线程,时时监听log输出情况,当检测到有应用程序启动时,则启动密码验证界面Thread thread = new Thread(new Runnable() { public void run() { while (flag) { System.out.println("////////////////////////////////////////////////////"); String str1;// log String str2;// 类名 String str3;// 包名 try { // Log.e(TAG, "========================="); Runtime localRuntime1 = Runtime.getRuntime(); String[] arrayOfString1 = new String[2]; arrayOfString1[0] = "logcat"; arrayOfString1[1] = "-c"; Process localProcess1 = localRuntime1.exec(arrayOfString1); int i = localProcess1.waitFor(); Runtime localRuntime2 = Runtime.getRuntime(); String[] arrayOfString2 = new String[2]; arrayOfString2[0] = "logcat"; arrayOfString2[1] = "ActivityManager:I *:S"; Process localProcess2 = localRuntime2.exec(arrayOfString2); InputStream localInputStream = localProcess2.getInputStream(); InputStreamReader reader = new InputStreamReader(localInputStream); BufferedReader localBufferedReader = new BufferedReader(reader); str1 = localBufferedReader.readLine();//获取log am = (ActivityManager) ProtectorService.this.getSystemService("activity"); ComponentName componentName = ((ActivityManager.RunningTaskInfo) ProtectorService.this.am .getRunningTasks(1).get(0)).topActivity; str2 = componentName.getClassName(); str3 = componentName.getPackageName(); //是否为启动一个应用 boolean start = str1.contains("android.intent.category.LAUNCHER"); //是否被保护/密码锁应用 boolean protector = mRunProList.contains(str3) || str3.equals("com.innofidei.protector"); System.out.println("ispass==" + !isPass+";start="+start+";protector="+protector); //如果应用被保护,且没有通过密码验证,则进入密码验证界面 //isPass标志应用是否通过密码验证 if (start && protector && !isPass) { System.out.println("----------in------------>"); // 如果是地址薄和拨号应用,则通过log来确定访问的是哪个tab页 if (str3.equals("com.android.contacts")) { Intent intent = new Intent(); intent.addCategory("android.intent.category.LAUNCHER"); intent.setAction("android.intent.action.MAIN"); if (str1.contains("DialtactsContactsEntryActivity")) { str2 = "com.android.contacts.DialtactsContactsEntryActivity"; } else if (str1.contains("DialtactsActivity")) { str2 = "com.android.contacts.DialtactsActivity"; } intent.setComponent(new ComponentName(str3, str2)); MyApplication.intent = intent; } else { MyApplication.intent = am.getRecentTasks(1, 0).get(0).baseIntent;//设置密码验证后需要启动应用的intent } Intent lockIntent = new Intent(ProtectorService.this, PasswordLockActivity.class); lockIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK).putExtra("pkg", str3) .putExtra("where", "service"); startActivity(lockIntent);//启动密码验证界面 System.out.println("----------finish------------>"); } isPass = false;//标记设置为false } catch (Exception localException) { return; } } } }); Smart.App.Protector也是读取log的方式? Smart.App.Protector应该不是,因为反编译的源码中没有看到读取log的代码,貌似是通过getRunningTask来监听应用程序的启动。我用过这种方法,虽然能监听到应用的启动,但是却不能阻止应用的启动,所以会造成启动的应用主界面先出现,然后才出现密码验证界面。另外,针对“地址薄”和“拨号”,他们在同一个apk,通过包名获取到的intent不能启动“地址薄”和“拨号”中的任一个,我通过读取log的方式,主要是为了解决这个问题,因为通过log我可以知道程序要启动的是那个tab页,从而自己new一个intent来启动应用。我不知道自己的问题是出在了哪里?求高手解决?在反编译的代码中,输入密码时的代码为 public void onClick(View paramView) { String str = ""; switch (paramView.getId()) { case 2131361831: case 2131361835: case 2131361839: default: label80: this.mPassEdit.append(str); case 2131361828: case 2131361829: case 2131361830: case 2131361832: case 2131361833: case 2131361834: case 2131361836: case 2131361837: case 2131361838: case 2131361841: case 2131361842: case 2131361840: } while (true) { return; str = "1"; break label80: str = "2"; break label80: str = "3"; break label80: str = "4"; break label80: str = "5"; break label80: str = "6"; break label80: str = "7"; break label80: str = "8"; break label80: str = "9"; break label80: str = "0"; break label80: this.mPassEdit.setText(""); continue; goHome(); } }感觉密码验证通过应该是调用的goHome()方法。 private void goHome() { Intent localIntent1 = new Intent(); localIntent1.setAction("android.intent.action.MAIN"); localIntent1.addCategory("android.intent.category.HOME"); localIntent1.addFlags(329252864);//这里的intent为什么没有指定是哪个activity呢?我这样写直接回到home界面的 startActivity(localIntent1);//下边这些代码又是做什么用的呢?看不明白呀 Intent localIntent2 = new Intent("android.intent.action.MAIN", null); localIntent2.addCategory("android.intent.category.HOME"); if (getPackageManager().queryIntentActivities(localIntent2, 0).size() > 1); while (true) { return; finish(); } } 看这里http://www.cnblogs.com/hangxin1940/archive/2011/09/29/2196001.html 这个必须用正则表达式匹配次才能快。我试过了,可以。但是我的需求是要求每一次用都弹出来,正则就不行了。因为同一个应用每一次使用过程中都会出现很多activity重复启动,这种方式只使用于一次性加密的情况,重复加密不太好,因为back健等不会导致activitymanager重新启动一个activity file.createNewFile()的Permission denied异常。。 新手报到 添加应用程序的桌面快捷方式 Host name may not be null 问题 基于android的师生答疑平台的开发 今天在用cocos2d android 导入Tiled地图时出现的问题,求大神指教 安卓报错了......... android 获取摄像头视频数据流只需要一帧 使用属性动画不停旋转图片的时候出现内存泄漏,跪求帮助该怎么解决!!! 使用HTTP协议的POST方式有问题! ADB命令无法输出信息怎么办 Android中创建100按钮, 并且通过控件ID获得控件对象
http://yangguangfu.iteye.com/blog/1063732
return ((ActivityManager.RunningTaskInfo) this.mActivityManager.getRunningTasks(1).get(0)).topActivity
.getPackageName();
}
public class ProtectorRunnable implements Runnable {
@Override
public void run() {
Log.e(TAG, "--------run-------------");
Handler handler_ = ProtectorService.this.handler;
Runnable runnable_ = ProtectorService.this.runnbale;
String packageName = getTopPackage();
String className = getTopClass();
Log.e(TAG, "packageName=" + packageName + "----className=" + className);
if (!packageName.equals(lastPkgName)) {
MyApplication.appStatus.remove(lastPkgName);
// Log.e(TAG, "appSt=atus");
}
int id = mActivityManager.getRunningAppProcesses().get(0).pid;
if (packageName.equals("com.android.settings") && !MyApplication.isPass(packageName)) {
System.out.println(getTopIntent());
// mActivityManager.restartPackage(packageName);// 关闭应用,这样就保证了每次打开应用都是重新启动的一个实例
System.out.println("id="+id);
android.os.Process.killProcess(id);
Intent intent1 = new Intent();
intent1.setClass(ProtectorService.this, PasswordLock.class);
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
lastPkgName = "";
startActivity(intent1);
}
handler_.post(runnable_);
}
}
看下activity的相关接口和生命周期,看能否在启动之前被截获
public void run() {
while (flag) {
System.out.println("////////////////////////////////////////////////////");
String str1;// log
String str2;// 类名
String str3;// 包名
try {
// Log.e(TAG, "=========================");
Runtime localRuntime1 = Runtime.getRuntime();
String[] arrayOfString1 = new String[2];
arrayOfString1[0] = "logcat";
arrayOfString1[1] = "-c";
Process localProcess1 = localRuntime1.exec(arrayOfString1);
int i = localProcess1.waitFor(); Runtime localRuntime2 = Runtime.getRuntime();
String[] arrayOfString2 = new String[2];
arrayOfString2[0] = "logcat";
arrayOfString2[1] = "ActivityManager:I *:S"; Process localProcess2 = localRuntime2.exec(arrayOfString2);
InputStream localInputStream = localProcess2.getInputStream();
InputStreamReader reader = new InputStreamReader(localInputStream);
BufferedReader localBufferedReader = new BufferedReader(reader); str1 = localBufferedReader.readLine();//获取log
am = (ActivityManager) ProtectorService.this.getSystemService("activity");
ComponentName componentName = ((ActivityManager.RunningTaskInfo) ProtectorService.this.am
.getRunningTasks(1).get(0)).topActivity;
str2 = componentName.getClassName();
str3 = componentName.getPackageName();
//是否为启动一个应用
boolean start = str1.contains("android.intent.category.LAUNCHER");
//是否被保护/密码锁应用
boolean protector = mRunProList.contains(str3) || str3.equals("com.innofidei.protector");
System.out.println("ispass==" + !isPass+";start="+start+";protector="+protector);
//如果应用被保护,且没有通过密码验证,则进入密码验证界面
//isPass标志应用是否通过密码验证
if (start && protector && !isPass) {
System.out.println("----------in------------>");
// 如果是地址薄和拨号应用,则通过log来确定访问的是哪个tab页
if (str3.equals("com.android.contacts")) {
Intent intent = new Intent();
intent.addCategory("android.intent.category.LAUNCHER");
intent.setAction("android.intent.action.MAIN");
if (str1.contains("DialtactsContactsEntryActivity")) {
str2 = "com.android.contacts.DialtactsContactsEntryActivity";
} else if (str1.contains("DialtactsActivity")) {
str2 = "com.android.contacts.DialtactsActivity";
}
intent.setComponent(new ComponentName(str3, str2));
MyApplication.intent = intent;
} else {
MyApplication.intent = am.getRecentTasks(1, 0).get(0).baseIntent;//设置密码验证后需要启动应用的intent
}
Intent lockIntent = new Intent(ProtectorService.this, PasswordLockActivity.class);
lockIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK).putExtra("pkg", str3)
.putExtra("where", "service");
startActivity(lockIntent);//启动密码验证界面
System.out.println("----------finish------------>");
}
isPass = false;//标记设置为false
} catch (Exception localException) {
return;
}
}
}
});
也是读取log的方式?
Smart.App.Protector应该不是,因为反编译的源码中没有看到读取log的代码,貌似是通过getRunningTask来监听应用程序的启动。我用过这种方法,虽然能监听到应用的启动,但是却不能阻止应用的启动,所以会造成启动的应用主界面先出现,然后才出现密码验证界面。另外,针对“地址薄”和“拨号”,他们在同一个apk,通过包名获取到的intent不能启动“地址薄”和“拨号”中的任一个,我通过读取log的方式,主要是为了解决这个问题,因为通过log我可以知道程序要启动的是那个tab页,从而自己new一个intent来启动应用。我不知道自己的问题是出在了哪里?求高手解决?
在反编译的代码中,输入密码时的代码为 public void onClick(View paramView)
{
String str = "";
switch (paramView.getId())
{
case 2131361831:
case 2131361835:
case 2131361839:
default:
label80: this.mPassEdit.append(str);
case 2131361828:
case 2131361829:
case 2131361830:
case 2131361832:
case 2131361833:
case 2131361834:
case 2131361836:
case 2131361837:
case 2131361838:
case 2131361841:
case 2131361842:
case 2131361840:
}
while (true)
{
return;
str = "1";
break label80:
str = "2";
break label80:
str = "3";
break label80:
str = "4";
break label80:
str = "5";
break label80:
str = "6";
break label80:
str = "7";
break label80:
str = "8";
break label80:
str = "9";
break label80:
str = "0";
break label80:
this.mPassEdit.setText("");
continue;
goHome();
}
}
感觉密码验证通过应该是调用的goHome()方法。
private void goHome()
{
Intent localIntent1 = new Intent();
localIntent1.setAction("android.intent.action.MAIN");
localIntent1.addCategory("android.intent.category.HOME");
localIntent1.addFlags(329252864);
//这里的intent为什么没有指定是哪个activity呢?我这样写直接回到home界面的
startActivity(localIntent1);
//下边这些代码又是做什么用的呢?看不明白呀
Intent localIntent2 = new Intent("android.intent.action.MAIN", null);
localIntent2.addCategory("android.intent.category.HOME");
if (getPackageManager().queryIntentActivities(localIntent2, 0).size() > 1);
while (true)
{
return;
finish();
}
}
http://www.cnblogs.com/hangxin1940/archive/2011/09/29/2196001.html
我试过了,可以。但是我的需求是要求每一次用都弹出来,正则就不行了。
因为同一个应用每一次使用过程中都会出现很多activity重复启动,这种方式只使用于一次性加密的情况,重复加密不太好,因为back健等不会导致activitymanager重新启动一个activity