App用户登入登出设计

App用户登入登出设计

流程图

流程图

注意,登出的时候须要关闭用户资源。若是不关闭的话,就会致使后台服务一直接收退出用户的消息等状况发生。android

资源

资源

登出

对于APP来讲,彻底退出是一项很是基本的功能,可是,这个功能要实现的比较好,也是比较困难的。git

最麻烦的地方就是:**账号切换了,可是还存在子进程或者子线程在运行上一个用户业务,致使完成的业务数据写入当前切换成功的用户数据库中。**若是拥有推送进程的话,那么还须要notify推送进程关闭,避免杀死Service进程又自重启。数据库

一般的作法是关闭全部服务,杀死全部的进程,而后重启。以下是一段比较完善的代码:app

/**
 * 重启App
 */
static public void killApp(Context context, boolean restart) {
	//重启
	if (restart) {
		Intent intent = new Intent(context, MyActivity.class);
		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		context.startActivity(intent);
	}
  
	//中止后台 service
	try {
		//读取全部的SERVICE信息
		PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SERVICES);
		if (packageInfo != null && packageInfo.services != null) {
			for (ServiceInfo serviceInfo : packageInfo.services) {
				try {
					Class cls = Class.forName(serviceInfo.name);
					context.stopService(new Intent(context, cls));
				} catch (ClassNotFoundException e) {
				}
			}
		}
	} catch (Exception e) {
		Log.e(MyActivity.class.getName(), e.getMessage(), e);
	}
	//杀死全部进程
	try {
		Set<String> processNameSet = new HashSet<String>();
		//读取 全部的Process
		{
			//读取Activity
			{
				PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
				if (packageInfo != null && packageInfo.activities != null) {
					for (ActivityInfo activityInfo : packageInfo.activities) {
						processNameSet.add(activityInfo.processName);
					}
				}
			}
			//读取Service
			{
				PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SERVICES);
				if (packageInfo != null && packageInfo.services != null) {
					for (ServiceInfo serviceInfo : packageInfo.services) {
						processNameSet.add(serviceInfo.processName);
					}
				}
			}
			//读取 RECEIVERS
			{
				PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_RECEIVERS);
				if (packageInfo != null && packageInfo.receivers != null) {
					for (ActivityInfo activityInfo : packageInfo.receivers) {
						processNameSet.add(activityInfo.processName);
					}
				}
			}
			//读取 PROVIDERS
			{
				PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_PROVIDERS);
				if (packageInfo != null && packageInfo.providers != null) {
					for (ProviderInfo providerInfo : packageInfo.providers) {
						processNameSet.add(providerInfo.processName);
					}
				}
			}
		}
		//关闭全部进程
		{
			int myPid = android.os.Process.myPid();
			ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
			Iterator iterator = mActivityManager.getRunningAppProcesses().iterator();
			while (iterator.hasNext()) {
				ActivityManager.RunningAppProcessInfo appProcess = (ActivityManager.RunningAppProcessInfo) iterator.next();
				if (processNameSet.contains(appProcess.processName)) {
					//先KILL其余进程
					if (appProcess.pid != myPid) {
						android.os.Process.killProcess(appProcess.pid);
					}
				}
			}
			//杀死本身
			android.os.Process.killProcess(myPid);
		}
	} catch (Exception e) {
		Log.e(MyActivity.class.getName(),e.getMessage(),e);
		throw new RuntimeException(e);
	}
}

核心思想是:ide

  1. 发送重启本身到主Activity事件到AMS
  2. 读取AndroidManifest.xml 中全部Service信息,调用stopService进行关闭,避免重启Service
  3. 杀死全部AndroidManifest.xml process 指向的进程,除了本身
  4. 杀死本身

这样子就能彻底退出app了,值得一提的是网上出现 restartPackage, killBackgroundProcesses 貌似在5.1上都不可行。固然,上面的代码测试环境,也是5.1了。测试

固然了,体验比较好的就是依次释放用户资源(线程池,数据库,后台Service等)。不过该方法实现起来比较困难。.net

总结

在用户的登入登出设计中,登入的时候须要注意用户是否以前登入过,而登出设计须要考虑TOKEN失效以及主动退出的问题。而登出设计的时候,还须要考虑关于我的资源(线程池,数据库,后台任务等)关闭的问题。线程

参考

相关文章
相关标签/搜索