您的位置:首页 > 移动开发 > Android开发

利用信鸽推送实现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" />  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐