利用信鸽推送实现Android登录后强制退出的功能(单点登录)
2017-03-30 19:52
645 查看
首先整理思路,先思考实现逻辑:
1.集成信鸽推送
2.实现自定义推送
3.在自定义推送中,接收推送的方法内启动强制退出功能。
思路逻辑很简单,但是实现起来就得一步一步做,先集成信鸽:
这里主要是参考官方开发文档即可
然后是实现自定义推送接受方,即自定义receiver
CustomReceiver.java
[java] view
plain copy
/**
*
*/
import u.upd.l;
import android.content.Context;
import android.content.Intent;
import com.dhcc.gpscarmanager_phone.CustomServices.ForceOfflineService;
import com.dhcc.gpscarmanager_phone.Util.L;
import com.tencent.android.tpush.XGPushBaseReceiver;
import com.tencent.android.tpush.XGPushClickedResult;
import com.tencent.android.tpush.XGPushRegisterResult;
import com.tencent.android.tpush.XGPushShowedResult;
import com.tencent.android.tpush.XGPushTextMessage;
public class CustomReceiver extends XGPushBaseReceiver {
/*
* (non-Javadoc)
*
* @see
* com.tencent.android.tpush.XGPushBaseReceiver#onDeleteTagResult(android
* .content.Context, int, java.lang.String)
*/
@Override
public void onDeleteTagResult(Context context, int arg1, String arg2) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see
* com.tencent.android.tpush.XGPushBaseReceiver#onNotifactionClickedResult
* (android.content.Context, com.tencent.android.tpush.XGPushClickedResult)
*/
@Override
public void onNotifactionClickedResult(Context context,
XGPushClickedResult arg1) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see
* com.tencent.android.tpush.XGPushBaseReceiver#onNotifactionShowedResult
* (android.content.Context, com.tencent.android.tpush.XGPushShowedResult)
*/
@Override
public void onNotifactionShowedResult(Context context,
XGPushShowedResult result) {
// TODO Auto-generated method stub
// 这里是测试代码,在接受到“下线”这两个字后,接收通知的应用强行下线
if ("下线".equals(result.getContent())) {
L.e(result.getContent());
context.getApplicationContext().startService(new Intent(context.getApplicationContext(), ForceOfflineService.class));
}
}
/*
* (non-Javadoc)
*
* @see
* com.tencent.android.tpush.XGPushBaseReceiver#onRegisterResult(android
* .content.Context, int, com.tencent.android.tpush.XGPushRegisterResult)
*/
@Override
public void onRegisterResult(Context context, int arg1,
XGPushRegisterResult arg2) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see
* com.tencent.android.tpush.XGPushBaseReceiver#onSetTagResult(android.content
* .Context, int, java.lang.String)
*/
@Override
public void onSetTagResult(Context context, int arg1, String arg2) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see
* com.tencent.android.tpush.XGPushBaseReceiver#onTextMessage(android.content
* .Context, com.tencent.android.tpush.XGPushTextMessage)
*/
@Override
public void onTextMessage(Context context, XGPushTextMessage message) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see
* com.tencent.android.tpush.XGPushBaseReceiver#onUnregisterResult(android
* .content.Context, int)
*/
@Override
public void onUnregisterResult(Context context, int arg1) {
// TODO Auto-generated method stub
}
}
在注册文件中加入该Revceiver的静态注册代码:
[html] view
plain copy
<receiver android:name="CustomReceivers.CustomReceiver" >
<intent-filter>
<!-- 接收消息透传 -->
<action android:name="com.tencent.android.tpush.action.PUSH_MESSAGE" />
<!-- 监听注册、反注册、设置/删除标签、通知被点击等处理结果 -->
<action android:name="com.tencent.android.tpush.action.FEEDBACK" />
</intent-filter>
</receiver>
然后注意这句代码:
[html] view
plain copy
if ("下线".equals(result.getContent())) {
L.e(result.getContent());
context.getApplicationContext().startService(new Intent(context.getApplicationContext(), ForceOfflineService.class));
}
由于目前是测试代码,所以我判断的是如果服务端发送的是“下线”的话,我就将该设备强制下线,在实际开发的过程中,其流程应当是
[html] view
plain copy
用户登录-> 判断当前的Token与数据库中存储的Token是否一致-> 如果不一致,则对数据库中的Token的用户发送约定好的下线通知,可以是参数也可以是字符串-> 手机端接到下线通知后,强制下线-> 服务端将新的Token保存到数据库中去,老的Token销毁
然后可以注意到,这里是启动了一个Service,然后利用Service进行下线操作的:
[html] view
plain copy
/**
*
*/
import com.dhcc.gpscarmanager_phone.CustomReceivers.ForceOfflineReceiver;
import com.dhcc.gpscarmanager_phone.Util.L;
import u.upd.l;
import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
public class ForceOfflineService extends Service {
private static final String TAG = "ForceOfflineService";
ForceOfflineReceiver forceOfflineReceiver;
@Override
public void onCreate() {
Log.i(TAG, "ExampleService-onCreate");
super.onCreate();
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction("com.dhcc.AppOffline");
forceOfflineReceiver=new ForceOfflineReceiver();
registerReceiver(forceOfflineReceiver, intentFilter);
Intent intent =new Intent("com.dhcc.AppOffline");
getApplicationContext().sendBroadcast(intent);
}
@Override
public void onStart(Intent intent, int startId) {
Log.i(TAG, "ExampleService-onStart");
super.onStart(intent, startId);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//执行文件的下载或者播放等操作
Log.i(TAG, "ExampleService-onStartCommand");
/*
* 这里返回状态有三个值,分别是:
* 1、START_STICKY:当服务进程在运行时被杀死,系统将会把它置为started状态,但是不保存其传递的Intent对象,之后,系统会尝试重新创建服务;
* 2、START_NOT_STICKY:当服务进程在运行时被杀死,并且没有新的Intent对象传递过来的话,系统将会把它置为started状态,
* 但是系统不会重新创建服务,直到startService(Intent intent)方法再次被调用;
* 3、START_REDELIVER_INTENT:当服务进程在运行时被杀死,它将会在隔一段时间后自动创建,并且最后一个传递的Intent对象将会再次传递过来。
*/
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "ExampleService-onBind");
return null;
}
@Override
public void onDestroy() {
Log.i(TAG, "ExampleService-onDestroy");
super.onDestroy();
unregisterReceiver(forceOfflineReceiver);
}
}
别忘了在配置文件中加入Service的注册:
[html] view
plain copy
<!-- 强制下线服务 -->
<service android:name="com.dhcc.gpscarmanager_phone.CustomServices.ForceOfflineService"/>
在OnCreate方法中加入了启动强制下线的Receiver的代码:
[html] view
plain copy
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.dhcc.AppOffline");
forceOfflineReceiver = new ForceOfflineReceiver();
registerReceiver(forceOfflineReceiver, intentFilter);
Intent intent = new Intent("com.dhcc.AppOffline");
getApplicationContext().sendBroadcast(intent);
这里要注意的是,不能直接用Context进行启动下线Receiver的操作,否则会报错:
[html] view
plain copy
IntentReceiver components are not allowed to register to receive intents
必须利用getApplicationContext的方式动态注册ForceOfflineRecevier(),不能用静态注册的方式,否则也会报上边同样的错误(但是这里不知道为什么)
具体解决原因参照:http://blog.csdn.net/eimsteim/article/details/7220920
然后启动这个ForceOfflineReceiver,他的内容是这样的:
[html] view
plain copy
import com.baidu.navisdk.util.common.Stopwatch;
import com.dhcc.gpscarmanager_phone.CustomServices.ForceOfflineService;
import com.dhcc.gpscarmanager_phone.CustomView.ActivityCollector;
import com.dhcc.gpscarmanager_phone.Module.Welcome.WelcomPage.LoginActivity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.view.WindowManager;
public class ForceOfflineReceiver extends BroadcastReceiver {
/*
* (non-Javadoc)
*
* @see android.content.BroadcastReceiver#onReceive(android.content.Context,
* android.content.Intent)
*/
@Override
public void onReceive(final Context context, Intent intent) {
// TODO Auto-generated method stub
intent = new Intent(context, ForceOfflineService.class);
context.stopService(intent);
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
dialogBuilder.setTitle("已下线");
dialogBuilder.setMessage("您的账户已在另一个设备登录,请尝试重新登陆");
dialogBuilder.setCancelable(false);
dialogBuilder.setPositiveButton("登 录", new OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
// TODO Auto-generated method stub
ActivityCollector.finishAll();
Intent intent = new Intent(context, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
});
AlertDialog alertDialog = dialogBuilder.create();
alertDialog.getWindow().setType(
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
alertDialog.show();
}
}
启动一个窗口,告诉用户你的账户在其他设备登录了,然后强制启动登录界面,并把之前启动的Activity都关闭掉,所以这里的关键类就是
ActivityCollector了:
[html] view
plain copy
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
public class ActivityCollector {
public static List<Activity> activities=new ArrayList<Activity>();
public static void addActivity(Activity activity){
activities.add(activity);
}
public static void removeActivity(Activity activity){
activities.remove(activity);
}
public static void finishAll(){
for(Activity activity:activities){
if(activity.isFinishing()){
activity.finish();
}
}
}
}
功能自己看,然后就是在你的基类BaseActivity里加入对应的代码:
[html] view
plain copy
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityCollector.addActivity(this);
}
protected void onDestroy(){
super.onDestroy();
ActivityCollector.removeActivity(this);
}
这样就把新启动的Activity管理起来了,然后在关闭的时候利用循环关闭对应的Activity即可了。
由于使用的是系统的弹出窗口,所以要在配置文件中加入这么一句权限:
[html] view
plain copy
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
1.集成信鸽推送
2.实现自定义推送
3.在自定义推送中,接收推送的方法内启动强制退出功能。
思路逻辑很简单,但是实现起来就得一步一步做,先集成信鸽:
这里主要是参考官方开发文档即可
然后是实现自定义推送接受方,即自定义receiver
CustomReceiver.java
[java] view
plain copy
/**
*
*/
import u.upd.l;
import android.content.Context;
import android.content.Intent;
import com.dhcc.gpscarmanager_phone.CustomServices.ForceOfflineService;
import com.dhcc.gpscarmanager_phone.Util.L;
import com.tencent.android.tpush.XGPushBaseReceiver;
import com.tencent.android.tpush.XGPushClickedResult;
import com.tencent.android.tpush.XGPushRegisterResult;
import com.tencent.android.tpush.XGPushShowedResult;
import com.tencent.android.tpush.XGPushTextMessage;
public class CustomReceiver extends XGPushBaseReceiver {
/*
* (non-Javadoc)
*
* @see
* com.tencent.android.tpush.XGPushBaseReceiver#onDeleteTagResult(android
* .content.Context, int, java.lang.String)
*/
@Override
public void onDeleteTagResult(Context context, int arg1, String arg2) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see
* com.tencent.android.tpush.XGPushBaseReceiver#onNotifactionClickedResult
* (android.content.Context, com.tencent.android.tpush.XGPushClickedResult)
*/
@Override
public void onNotifactionClickedResult(Context context,
XGPushClickedResult arg1) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see
* com.tencent.android.tpush.XGPushBaseReceiver#onNotifactionShowedResult
* (android.content.Context, com.tencent.android.tpush.XGPushShowedResult)
*/
@Override
public void onNotifactionShowedResult(Context context,
XGPushShowedResult result) {
// TODO Auto-generated method stub
// 这里是测试代码,在接受到“下线”这两个字后,接收通知的应用强行下线
if ("下线".equals(result.getContent())) {
L.e(result.getContent());
context.getApplicationContext().startService(new Intent(context.getApplicationContext(), ForceOfflineService.class));
}
}
/*
* (non-Javadoc)
*
* @see
* com.tencent.android.tpush.XGPushBaseReceiver#onRegisterResult(android
* .content.Context, int, com.tencent.android.tpush.XGPushRegisterResult)
*/
@Override
public void onRegisterResult(Context context, int arg1,
XGPushRegisterResult arg2) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see
* com.tencent.android.tpush.XGPushBaseReceiver#onSetTagResult(android.content
* .Context, int, java.lang.String)
*/
@Override
public void onSetTagResult(Context context, int arg1, String arg2) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see
* com.tencent.android.tpush.XGPushBaseReceiver#onTextMessage(android.content
* .Context, com.tencent.android.tpush.XGPushTextMessage)
*/
@Override
public void onTextMessage(Context context, XGPushTextMessage message) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see
* com.tencent.android.tpush.XGPushBaseReceiver#onUnregisterResult(android
* .content.Context, int)
*/
@Override
public void onUnregisterResult(Context context, int arg1) {
// TODO Auto-generated method stub
}
}
在注册文件中加入该Revceiver的静态注册代码:
[html] view
plain copy
<receiver android:name="CustomReceivers.CustomReceiver" >
<intent-filter>
<!-- 接收消息透传 -->
<action android:name="com.tencent.android.tpush.action.PUSH_MESSAGE" />
<!-- 监听注册、反注册、设置/删除标签、通知被点击等处理结果 -->
<action android:name="com.tencent.android.tpush.action.FEEDBACK" />
</intent-filter>
</receiver>
然后注意这句代码:
[html] view
plain copy
if ("下线".equals(result.getContent())) {
L.e(result.getContent());
context.getApplicationContext().startService(new Intent(context.getApplicationContext(), ForceOfflineService.class));
}
由于目前是测试代码,所以我判断的是如果服务端发送的是“下线”的话,我就将该设备强制下线,在实际开发的过程中,其流程应当是
[html] view
plain copy
用户登录-> 判断当前的Token与数据库中存储的Token是否一致-> 如果不一致,则对数据库中的Token的用户发送约定好的下线通知,可以是参数也可以是字符串-> 手机端接到下线通知后,强制下线-> 服务端将新的Token保存到数据库中去,老的Token销毁
然后可以注意到,这里是启动了一个Service,然后利用Service进行下线操作的:
[html] view
plain copy
/**
*
*/
import com.dhcc.gpscarmanager_phone.CustomReceivers.ForceOfflineReceiver;
import com.dhcc.gpscarmanager_phone.Util.L;
import u.upd.l;
import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
public class ForceOfflineService extends Service {
private static final String TAG = "ForceOfflineService";
ForceOfflineReceiver forceOfflineReceiver;
@Override
public void onCreate() {
Log.i(TAG, "ExampleService-onCreate");
super.onCreate();
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction("com.dhcc.AppOffline");
forceOfflineReceiver=new ForceOfflineReceiver();
registerReceiver(forceOfflineReceiver, intentFilter);
Intent intent =new Intent("com.dhcc.AppOffline");
getApplicationContext().sendBroadcast(intent);
}
@Override
public void onStart(Intent intent, int startId) {
Log.i(TAG, "ExampleService-onStart");
super.onStart(intent, startId);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//执行文件的下载或者播放等操作
Log.i(TAG, "ExampleService-onStartCommand");
/*
* 这里返回状态有三个值,分别是:
* 1、START_STICKY:当服务进程在运行时被杀死,系统将会把它置为started状态,但是不保存其传递的Intent对象,之后,系统会尝试重新创建服务;
* 2、START_NOT_STICKY:当服务进程在运行时被杀死,并且没有新的Intent对象传递过来的话,系统将会把它置为started状态,
* 但是系统不会重新创建服务,直到startService(Intent intent)方法再次被调用;
* 3、START_REDELIVER_INTENT:当服务进程在运行时被杀死,它将会在隔一段时间后自动创建,并且最后一个传递的Intent对象将会再次传递过来。
*/
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "ExampleService-onBind");
return null;
}
@Override
public void onDestroy() {
Log.i(TAG, "ExampleService-onDestroy");
super.onDestroy();
unregisterReceiver(forceOfflineReceiver);
}
}
别忘了在配置文件中加入Service的注册:
[html] view
plain copy
<!-- 强制下线服务 -->
<service android:name="com.dhcc.gpscarmanager_phone.CustomServices.ForceOfflineService"/>
在OnCreate方法中加入了启动强制下线的Receiver的代码:
[html] view
plain copy
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.dhcc.AppOffline");
forceOfflineReceiver = new ForceOfflineReceiver();
registerReceiver(forceOfflineReceiver, intentFilter);
Intent intent = new Intent("com.dhcc.AppOffline");
getApplicationContext().sendBroadcast(intent);
这里要注意的是,不能直接用Context进行启动下线Receiver的操作,否则会报错:
[html] view
plain copy
IntentReceiver components are not allowed to register to receive intents
必须利用getApplicationContext的方式动态注册ForceOfflineRecevier(),不能用静态注册的方式,否则也会报上边同样的错误(但是这里不知道为什么)
具体解决原因参照:http://blog.csdn.net/eimsteim/article/details/7220920
然后启动这个ForceOfflineReceiver,他的内容是这样的:
[html] view
plain copy
import com.baidu.navisdk.util.common.Stopwatch;
import com.dhcc.gpscarmanager_phone.CustomServices.ForceOfflineService;
import com.dhcc.gpscarmanager_phone.CustomView.ActivityCollector;
import com.dhcc.gpscarmanager_phone.Module.Welcome.WelcomPage.LoginActivity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.view.WindowManager;
public class ForceOfflineReceiver extends BroadcastReceiver {
/*
* (non-Javadoc)
*
* @see android.content.BroadcastReceiver#onReceive(android.content.Context,
* android.content.Intent)
*/
@Override
public void onReceive(final Context context, Intent intent) {
// TODO Auto-generated method stub
intent = new Intent(context, ForceOfflineService.class);
context.stopService(intent);
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
dialogBuilder.setTitle("已下线");
dialogBuilder.setMessage("您的账户已在另一个设备登录,请尝试重新登陆");
dialogBuilder.setCancelable(false);
dialogBuilder.setPositiveButton("登 录", new OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
// TODO Auto-generated method stub
ActivityCollector.finishAll();
Intent intent = new Intent(context, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
});
AlertDialog alertDialog = dialogBuilder.create();
alertDialog.getWindow().setType(
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
alertDialog.show();
}
}
启动一个窗口,告诉用户你的账户在其他设备登录了,然后强制启动登录界面,并把之前启动的Activity都关闭掉,所以这里的关键类就是
ActivityCollector了:
[html] view
plain copy
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
public class ActivityCollector {
public static List<Activity> activities=new ArrayList<Activity>();
public static void addActivity(Activity activity){
activities.add(activity);
}
public static void removeActivity(Activity activity){
activities.remove(activity);
}
public static void finishAll(){
for(Activity activity:activities){
if(activity.isFinishing()){
activity.finish();
}
}
}
}
功能自己看,然后就是在你的基类BaseActivity里加入对应的代码:
[html] view
plain copy
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityCollector.addActivity(this);
}
protected void onDestroy(){
super.onDestroy();
ActivityCollector.removeActivity(this);
}
这样就把新启动的Activity管理起来了,然后在关闭的时候利用循环关闭对应的Activity即可了。
由于使用的是系统的弹出窗口,所以要在配置文件中加入这么一句权限:
[html] view
plain copy
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
相关文章推荐
- 利用信鸽推送实现Android登录后强制退出的功能(单点登录)
- 利用信鸽推送实现登录后强制退出的功能
- Android之利用广播实现完全退出程序功能
- Android高效率编码-第三方SDK详解系列(二)——Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能
- android 利用广播实现程序的强制退出
- Android高效率编码-第三方SDK详解系列(二)——Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能
- Android利用CountDownTimer实现倒计时功能 Android实现停留5s跳转到登录页面
- android定时定位 - 利用百度定位API来实现定时定位功能
- 【Android游戏开发十六】Android Gesture之【触摸屏手势识别】操作!利用触摸屏手势实现一个简单切换图片的功能!
- Android 实现推送功能
- android学习—— 简单的实现 android 退出app 的功能, 非 restartPackage
- 【转】android利用数据库实现搜索联想功能
- android定时定位 - 利用百度定位API来实现定时定位功能
- Android应用程序开发教程:实现一个功能比较完善的登录对话框
- Android利用CountDownTimer类实现倒计时功能
- androidpn实现android消息推送功能——服务器端详解
- Android开发实现新浪账号授权登录的功能
- 利用 android手机DLNA功能,实现手机视频无线播放到电脑、电视
- Android: 如何利用Handler处理和发送消息来实现页面刷新的功能
- 【Android游戏开发十六】Android Gesture之【触摸屏手势识别】操作!利用触摸屏手势实现一个简单切换图片的功能!