轉載請註明文章出處和作者!
出處:http://blog.csdn.net/xl19862005
作者:大熊(Xandy)
由於項目的要求,需要限制用戶安裝APP的數量,對android app安裝流程瞭解的都知道,核心的東西都在installd這個服務裏面,我這裏所做的處理也在這裏面。
installd的源碼位於frameworks/native/cmds/installd(android5.1),這個服務隨init啓來之後,通過socket和上層進行數據交互,在installd裏面能處理的命令集如下(android版本不同,這些命令略有差異):
struct cmdinfo cmds[] = {
{ "ping", 0, do_ping },
{ "install", 4, do_install },
{ "dexopt", 6, do_dexopt },
{ "markbootcomplete", 1, do_mark_boot_complete },
{ "movedex", 3, do_move_dex },
{ "rmdex", 2, do_rm_dex },
{ "remove", 2, do_remove },
{ "rename", 2, do_rename },
{ "fixuid", 3, do_fixuid },
{ "freecache", 1, do_free_cache },
{ "rmcache", 2, do_rm_cache },
{ "rmcodecache", 2, do_rm_code_cache },
{ "getsize", 7, do_get_size },
{ "rmuserdata", 2, do_rm_user_data },
{ "movefiles", 0, do_movefiles },
{ "linklib", 3, do_linklib },
{ "mkuserdata", 4, do_mk_user_data },
{ "mkuserconfig", 1, do_mk_user_config },
{ "rmuser", 1, do_rm_user },
{ "idmap", 3, do_idmap },
{ "restorecondata", 3, do_restorecon_data },
{ "patchoat", 5, do_patchoat },
};
對app限制安裝只看install這個命令的處理函數,在frameworks/native/cmds/installd/commands.c這個文件中的install函數這裏,我增加了如下處理代碼:
int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo)
{
………………
/****************************Xandy add for app install control***************************/
if(app_install_cnt_ctrl() < 0)
return -1;
………………
}
相關實現代碼如下:
#define APP_CNT_PATH "/data/misc/installctrl/cnt"
static int app_cnt = 0;
/********從文件讀取用戶安裝APP的數量*******/
static int get_user_install_app_cnt(void)
{
int fd;
char buf[10];
fd = open(APP_CNT_PATH, O_RDONLY | O_NONBLOCK);
if(fd < 0)
{
ALOGE("File:%S doesn't exist", AP_CNT_PATH);
return 0;
}
if(read(fd, buf, 10) < 0)
{
ALOGE("Read file:%s error",APP_CNT_PATH);
return 0;
}
close(fd);
return atoi(buf);
}
/***********保存用戶安裝APP的數量*************/
static void save_user_install_app_cnt(void)
{
FILE* fp = NULL;
int fd;
char buf[10];
app_cnt++;//a new app install
sprintf(buf, "%d", app_cnt);
if(acces(APP_CNT_PATH, F_OK) != 0)
{
fp = fopen(APP_CNT_PATH, "w+");
fputs(buf, fp);
fclose(fp);
fp = NULL;
}
else
{
fd = open(APP_CNT_PATH, O_RDWR);
if(fd >= 0)
{
write(fd, buf, 10);
close(fd);
}
}
}
/*********獲取開機完成狀態*********/
static int boot_animation_finish(void)
{
char value[PROPERTY_VALUE_MAX];
property_get("service.bootanim.exit",value, "1");
return atoi(value);
}
//************************************
static int app_install_cnt_ctrl(void)
{
char value[PROPERTY_VALUE_MAX];
int ctrl_cnt;
if(boot_animation_finish() == 1)
{
property_get("ro.ctrl.app_install_cnt", value, "0");//用戶可安裝的APP數量,通過ro.ctrl.app_install_cnt這個prop獲取
ctrl_cnt = atoi(value);
app_cnt = get_user_install_app_cnt();
if(app_cnt < ctrl_cnt)
{
save_user_install_app_cnt();
return 0;
}
else
return -1;
}
return 0;
}
實現原理:
將每次用戶安裝的APP數目記錄到文件,當安裝的數目達到由ro.ctrl.app_install_cnt這個prop設置的上限值時,直接退出install處理流程。
上面的代碼我是留了一個小後門的(在某種情況下可以安裝APP,這也是方法以後自己調試的方便),仔細的你肯定能發現,這裏就不直說了哈,有需要的小夥伴自己慢慢琢磨……