第五天:程序锁和进程管理

来源:互联网 发布:吉林省网络培训学院 编辑:程序博客网 时间:2024/06/01 11:02
/**************************************************************************/分享还是很重要的,不过主要是系统完成的,你有新浪,QQ等它会自动找出来让其分享,让用户选择。想要实现异步刷新那个listView,第一,把新的值赋值给适配器,第二,适配器调用notify......如何保存页面在加载时间,用户点击界面不会出错,因为这个时间数据还没有过来,用户一直在点击的话,很可能报空针异常,现在我们引入一个变量去判断,极其好的方法,是非常通用的方法。经测试果断分享可以分享给微博等。(分享源码)Intent shareIntent = new Intent();shareIntent.setAction(Intent.ACTION_SEND);shareIntent.setType("text/plain");shareIntent.putExtra(Intent.EXTRA_SUBJECT, "分享");shareIntent.putExtra(Intent.EXTRA_TEXT,"推荐你使用一个程序" + item.getAppName());startActivity(shareIntent);上面说过了,最致使的一点,当一个数据在加载的过程中,有那个ProgressBar在加载,你乱点一气,触发了一些事件,而这些事件里面的数据还没有加载过来,那么马上会报错,这就模态要面临的一个大问题。/**在适配器里面的方法。 * 这个方法十分 重要,你想要动态更改它的值 ,并且不刷新 ,那么你就要通知适配器,你的最新数据是什么, * 然后再用adapter.notifyDataSetChanged();用异步刷新 。 * @param appInfos */public void setAppInfos(List<AppInfo> appInfos){this.list = appInfos;}activity中的应用(异步刷新):adapter.setAppInfos(userAppInfos);adapter.notifyDataSetChanged();这个应用程序管理器里面包含的一些思想十分重要。第一、listView优化://如果你不做成静态的,每次它都会栈内存中new出一个新引用 。 静态这个东西是我的弱点 。private static ImageView iv;private static TextView tv;/** * View convertView (转化view对象 ,历史view对象的缓存) convertview 就是拖动的时候被回收掉的view对象 * 每个条目每次显示的时间都会调用这个方法,所以每次都会生成不同的convertView,当某个已经生成的条目再次调用它的时间如果 * 发现这个convertView是存在的,那么肯定是与之对应的那个,所以用缓存中的convertView即可。 */@Overridepublic View getView(int position, View convertView, ViewGroup parent) {AppInfo  appInfo = new AppInfo();appInfo = list.get(position);View view ;//如果发现当前条目的convertView为空,我们可以判定,这个条目一定还没有显示过if (convertView == null) {Log.i(TAG,"通过资源文件 创建view对象");//这个是通过反射等生成的非常消耗内存,每个条目调用 一次就行了。view = View.inflate(context, R.layout.app_item, null);}else {Log.i(TAG,"使用历史缓存view对象");view = convertView;}iv = (ImageView) view.findViewById(R.id.iv_app_icon);tv = (TextView) view.findViewById(R.id.tv_app_name);iv.setImageDrawable(appInfo.getIcon());tv.setText(appInfo.getAppName());return view;}第二、设置一个变量,在加载数据的时间所有的事件都不可点击,加载完毕以后才可以点击(否则肯定空针异常),肯定是结合了消息机制来做的。第三、在切换的时间做的比较好。程序锁功能 :1. 用户要开启的这个应用是哪一个应用.   寻找系统里面是不是这样的广播事件,如果这样直接注册一个广播接收者。不过有的应用不行,所以排除 。   我们发现每个应用程序打开的时间ActivityManager都会暴露出来一段Log.2. 判断这个应用的包名 程序名 是否是要锁定的应用名字一致ActvityManager里面有个方法可以得到最近应用,与长按Home键盘得到的东西是一致的。特别好用的。可以得到当前正在运行的任务栈里面的信息。 ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);List<RunningTaskInfo>  infos = manager.getRunningTasks(2);for (RunningTaskInfo info : infos) {System.out.println("tt  "+info.topActivity.getPackageName());}想要调用同一个进程里面服务里的方法,要绑定这个服务。想要跨进程访问,就用AIDL。之所以绑定服务能够调用服务里面的方法,主要是因为在onBinder方法里面能够返回一个IBinder对象。先自己做试验,常规的。如果是绑定,同生共死的,如果你退出activity会出错。先开启,后绑定方式。一个服务也只能被解除绑定一次,多次会出异常。服务总结:1、startService()开启的服务会长期运行在后台与服务调用者无关,调用者结束,服务不会结束,不能调用服务里面的方法。2、bindService()服务和调用者绑定在一起,如果调用者挂掉了,服务也会终止,调用者可以访问服务里面的方法。如果我们既要服务长期在后台运行,又要去调用服务里面的方法。那么,1、startService()保证服务长期在后台运行,2、bindService()把服务绑定,调用服务里面的方法。那么这种如何结束服务呢,首先解绑服务,然后再stop服务这样就结束了。在单独使用绑定服务的时间,如果调用者关了,但是服务没有停止 ,这样会报出异常,如果你该服务你已经解除绑定过了,再次解绑还会出错。针对第一种调用者关了,那么应该在调用者的activity里面重写onDestory()方法,并且在里面调用 unbind()方法,这样当调用者退出时间,它也会自动退出。复习一下相对布局。再次证明,使用模态就用帧布局。复杂动画用AnimationSet.其实Oncreate()相当于main,所有的方法都 要写在里面。否则就相当于它没有被调用 ,除了回调函数。动画,位移动画,安卓中,好看的东西,无非是动画和背景两种。TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f,Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.0f,Animation.RELATIVE_TO_SELF, 0.0f);ta.setDuration(500);没有把频繁访问数据库的操作放在getView里面,而是而先把数据库里面的数据放到 一个集合里面,让集合去判断它存在不存在,然后当再有数据库的添加和删除时间,再动态往这个集合里面存 ,放数据。AppInfo appInfo = infos.get(position);//出现问题了,原来listview只是第一屏显示是新创建的,其它用的都是缓存,你锁后,那个东西存储到缓存中,当下面的再调用这个布局的时间,直接默认它是这样。//所以我们在这里面动态设置一把即可。还有你在这绝对不能用数据库判断,而是放在 一个集合里面。iv_lock_status = (ImageView) view.findViewById(R.id.iv_app_lock_status);iv = (ImageView) view.findViewById(R.id.iv_app_icon);tv_appName = (TextView) view.findViewById(R.id.tv_app_name);tv_packName = (TextView) view.findViewById(R.id.tv_app_packname);if (lockappinfos.contains(appInfo.getPackName())) {iv_lock_status.setImageResource(R.drawable.lock);}else {iv_lock_status.setImageResource(R.drawable.unlock);}iv.setImageDrawable(infos.get(position).getIcon());tv_appName.setText(infos.get(position).getAppName());tv_packName.setText(infos.get(position).getPackName());//如果发现已锁定,则让它不锁定,否则让它锁定 if (lockAppDao.find(appName)) {imageView.setImageResource(R.drawable.unlock);lockAppDao.delete(appName);lockappinfos.remove(appName);}else {lockAppDao.insert(appName);imageView.setImageResource(R.drawable.lock);lockappinfos.add(appName);}看门狗的逻辑:看门狗服务第一创建出的时间,应该去找任务栈中的应用是否在锁定状态(访问数据库知道)太厉害了,让一个服务一直反复监听执行,原来是用循环。服务里面激活任务栈:在安卓中数据通信就两点,一是跟后台持久化的东西,二是前台各个控件之间通信。掌握到这两点即可。结束当前activity,finish()、操,后台开启一个服务,弄一个死循环,一直在获取当前运行的activity是不是在锁定表中,如果是果断弹出相应的输入密码界面。stopService(iservic) 会调用服务中的ondestory()方法。其实这个看门狗非常简单,就是在发现被锁定的程序运行时间,赶紧自己弹出一个输入密码的activity去在当前任务栈中新加一个,但是,如果用户按后退的时间就挂了,会回去要打开的程序中,所以屏蔽后退按钮。todo:1. 用户输入密码正确. 通知看门狗 临时的停止对这个程序的保护 就需要调用服务里面的方法 。2. 更新完毕数据库之后 通知看门狗 更新lockapp集合里面的内容// 判断当前前台进程的包名 是否与luncher的包名 相同 // 清空temp集合activity之所以能够调用服务里面的方法就是因为onBind()方法能够返回IBinder的对象。凡是你在一个Acitivity里面绑定了一个服务就一定不要忘记了在activity里面的ondestory()里面把unbindSerivce()解除绑定。有一个问题,打开的activity,LockScreenActivity这个会加入到360safe的这个软件的栈顶,当你打开360safe的时间会把LockScreenActivity显示出来,所以我们应该把这个LockScreenActivity设置启动模式为单例。第二个问题是不是把获取所有应用的操作放在子线程里面,太浪费性能了,要用内容提供者。然后在activity写一个内容观察者,可以观察到数据的变化,那岂不很好。当数据改变的时间,再去更新lockapps集合里面的内容。发现了一个天大的秘密,原来只要涉及数据库频繁操作的,一般情况下都不直接和它交互,因为这样太浪费感情了,如果只是取的比较多,那么把它放在一个集合里面,用contains这个方法,判断,只需要从数据库读取一次,还有一个就是你在过程中GRUD可能会有,这个时间应该把这个对数据库的操作写成一个内容提供者,然后在activity里面写一个内容观察者,当数据发生变化的时间才去改变它。原来第一个问题是这样解决的,如果输入密码正确,则往服务里面的一个临时集合里面加一个数据,在判断的时间加上集合中有没有这个,有的话此次打开 ,并不是非要说把数据库给改变,此方法是多么的好呀。第二个问题是,我们不能每次都从数据库里面读取最新的数据吧,所以我们用一个把它封装成一个内容提供者,当内容改变的时间才去更新。这个东西要好好 看看的。<!-- 被锁程序读取数据库的内容提供者 --><provider android:name=".provider.AppLockProvider" android:authorities="cn.itcast.applockprovider"></provider>写好以后,再调用GRUD时间getContentResolver().delete(Uri.parse("content://cn.itcast.applockprovider/delete"), null, new String[]{appName});第二个作用就是可以为其注册一个内容观察者,当数据变化的时间才触发onChange事件。//注册内容观察者getContentResolver().registerContentObserver(Uri.parse("content://cn.itcast.applockprovider"),true, new MyObserver(new Handler()));守护进程。//输入密码后,再次进入的三种做法 。做法1> 当用户回到桌面应用后 ,下一次在进入计算器 需要输入密码做法2> 倒计时60秒 , 60过后 需要再次输入密码// 开启一个子线程 60秒后清空这个temp集合做法3> 当用户关闭手机屏幕后,下一次进入程序的时候 需要输入密码 (360的做法)读log的方式开发的程序锁.耗电量 低一些 效率低.

原创粉丝点击