Androidpn学习笔记-客户端代码分析

客户端代码分析


DemoAppActivity

程序以DemoAppActivity启动,在DemoAppActivity的onCreate时,创建一个ServiceManager对象,并将自身作为Context传递给ServiceManager对象,之后调用ServiceManager对象的startService,代码如下:

	// Start the service
        ServiceManager serviceManager = new ServiceManager(this);
        serviceManager.setNotificationIcon(R.drawable.notification);
        serviceManager.startService();


ServiceManager

ServiceManager是一个简单的类,主要功能就是从文件读取配置参数,将配置参数导入SharedPreferences,启动和停止NotificationService服务。

ServiceManager的构造函数中进行读取参数和导入参数的操作。

ServiceManager:: startService启动NotificationService服务:

public void startService() {
        Thread serviceThread = new Thread(new Runnable() {
            @Override
            public void run() {
                Intent intent = NotificationService.getIntent();
                context.startService(intent);//context就是DemoAppActivity对象
            }
        });
        serviceThread.start();
    }

ServiceManager:: stopService停止NotificationService服务:

public void stopService() {
        Intent intent = NotificationService.getIntent();
        context.stopService(intent);
    }

NotificationService

对象构造时创建四个对象:NotificationReceiver、ConnectivityReceiver、PhoneStateChangeListener、ExecutorService(单线程线程池对象)、TaskSubmitter和TaskTracker。

TaskSubmitter对象负责将从Runnable继承的线程任务提交给ExecutorService对象。

NotificationService:: onCreate创建一个XmppManager对象,然后通过TaskSubmitter对象提交一个线程任务:

	taskSubmitter.submit(new Runnable() {
            public void run() {
                NotificationService.this.start();
            }
        });
NotificationService:: onDestroy调用stop函数:

@Override
    public void onDestroy() {
        Log.d(LOGTAG, "onDestroy()...");
        stop();
    }
NotificationService:: start中注册广播接收器NotificationReceiver对象和ConnectivityReceiver对象,然后调用XmppManager对象的connect函数。
private void start() {
        Log.d(LOGTAG, "start()...");
        registerNotificationReceiver();
        registerConnectivityReceiver();
        // Intent intent = getIntent();
        // startService(intent);
        xmppManager.connect();
}
NotificationReceiver 对象接收以下类型广播:
filter.addAction(Constants.ACTION_SHOW_NOTIFICATION);
ConnectivityReceiver 对象接收以下类型广播:
filter.addAction(android.net.ConnectivityManager.CONNECTIVITY_ACTION);
NotificationService :: registerConnectivityReceiver函数中开始监听手机状态变化:
		telephonyManager.listen(phoneStateListener,
                PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
NotificationService:: stop中注销广播接收器NotificationReceiver对象和ConnectivityReceiver对象,然后调用XmppManager对象的disconnect函数,最后停止ExecutorService单线程线程池对象。
private void stop() {
        Log.d(LOGTAG, "stop()...");
        unregisterNotificationReceiver();
        unregisterConnectivityReceiver();
        xmppManager.disconnect();
        executorService.shutdown();
    }
NotificationService:: connect函数通过TaskSubmitter对象提交一个调用XmppManager对象的connect函数的线程任务。
NotificationService:: disconnect函数通过TaskSubmitter对象提交一个调用XmppManager对象的disconnect函数的线程任务。

PhoneStateChangeListener

PhoneStateChangeListener对象监听手机的状态改变广播,它收到DATA_CONNECTED广播后调用NotificationService对象的connect函数。


TaskSubmitter

TaskSubmitter对象负责将从Runnable继承的线程任务提交给ExecutorService对象:

@SuppressWarnings("unchecked")
        public Future submit(Runnable task) {
            Future result = null;
            if (!notificationService.getExecutorService().isTerminated()
                    && !notificationService.getExecutorService().isShutdown()
                    && task != null) {
                result = notificationService.getExecutorService().submit(task);
            }
            return result;
        }

TaskTracker

TaskTracker对象负责为NotificationService对象的待运行的线程任务计数。


ConnectivityReceiver

ConnectivityReceiver在收到android.net.ConnectivityManager.CONNECTIVITY_ACTION广播后,判断网络是否连接,连接了则调用NotificationService对象的connect函数,否则调用NotificationService对象的disconnect函数。


NotificationReceiver

NotificationReceiver对象收到Constants.ACTION_SHOW_NOTIFICATION广播后,从Intent参数中解析出参数,创建一个Notifier对象,并调用其notify函数:

	if (Constants.ACTION_SHOW_NOTIFICATION.equals(action)) {
            String notificationId = intent
                    .getStringExtra(Constants.NOTIFICATION_ID);
            String notificationApiKey = intent
                    .getStringExtra(Constants.NOTIFICATION_API_KEY);
            String notificationTitle = intent
                    .getStringExtra(Constants.NOTIFICATION_TITLE);
            String notificationMessage = intent
                    .getStringExtra(Constants.NOTIFICATION_MESSAGE);
            String notificationUri = intent
                    .getStringExtra(Constants.NOTIFICATION_URI);

            Log.d(LOGTAG, "notificationId=" + notificationId);
            Log.d(LOGTAG, "notificationApiKey=" + notificationApiKey);
            Log.d(LOGTAG, "notificationTitle=" + notificationTitle);
            Log.d(LOGTAG, "notificationMessage=" + notificationMessage);
            Log.d(LOGTAG, "notificationUri=" + notificationUri);

            Notifier notifier = new Notifier(context);
            notifier.notify(notificationId, notificationApiKey,
                    notificationTitle, notificationMessage, notificationUri);
        }

Notifier

Notifier对象负责通知状态栏显示收到的消息。


XmppManager

XmppManager在构造函数中创建PersistentConnectionListenerxmpp连接监视对象和NotificationPacketListener返回包监视对象。

App启动即调用XmppManager对象的connect函数。该函数依次启动三个线程任务:ConnectTaskRegisterTaskLoginTask,之后便进入接收消息的状态。

XmppManager对象使用org.jivesoftware.smack.XMPPConnection对象和xmpp服务器保持连接。

ConnectTask用于连接服务器,连接成功后,org.jivesoftware.smack.XMPPConnection对象的isConnected方法返回true

RegisterTask用于发送包含用户名和密码的注册包给服务器,在服务器注册一个用户。

LoginTask 用于登陆服务器,获得服务器授权,登陆服务器成功后, org.jivesoftware.smack.XMPPConnection 对象的 isAuthenticated 方法返回 true

ConnectTask

1)用服务器IP和端口创建org.jivesoftware.smack.ConnectionConfiguration连接配置对象:

		ConnectionConfiguration connConfig = new ConnectionConfiguration(
                        xmppHost, xmppPort);
                // connConfig.setSecurityMode(SecurityMode.disabled);
                connConfig.setSecurityMode(SecurityMode.required);
                connConfig.setSASLAuthenticationEnabled(false);
                connConfig.setCompressionEnabled(false);
2)用连接配置对象创建org.jivesoftware.smack.XMPPConnection对象:
		XMPPConnection connection = new XMPPConnection(connConfig);
                xmppManager.setConnection(connection);
3) 连接服务器:
		connection.connect();
                 Log.i(LOGTAG, "XMPP connected successfully");
                 // packet provider
                 ProviderManager.getInstance().addIQProvider("notification",
                            "androidpn:iq:notification",
                            new NotificationIQProvider());

RegisterTask

1)创建一个Registration注册包对象:

		Registration registration = new Registration();
2)创建一个PacketFilter对象:
		PacketFilter packetFilter = new AndFilter(new PacketIDFilter(
                        registration.getPacketID()), new PacketTypeFilter(
                        IQ.class));
3)创建一个PacketListener返回包监听对象:
		PacketListener packetListener = new PacketListener() {

                    public void processPacket(Packet packet) {
                        Log.d("RegisterTask.PacketListener",
                                "processPacket().....");
                        Log.d("RegisterTask.PacketListener", "packet="
                                + packet.toXML());

                        if (packet instanceof IQ) {
                            IQ response = (IQ) packet;
                            if (response.getType() == IQ.Type.ERROR) {
                                if (!response.getError().toString().contains(
                                        "409")) {
                                    Log.e(LOGTAG,
                                            "Unknown error while registering XMPP account! "
                                                    + response.getError()
                                                            .getCondition());
                                }
                            } else if (response.getType() == IQ.Type.RESULT) {
                                xmppManager.setUsername(newUsername);
                                xmppManager.setPassword(newPassword);
                                Log.d(LOGTAG, "username=" + newUsername);
                                Log.d(LOGTAG, "password=" + newPassword);

                                Editor editor = sharedPrefs.edit();
                                editor.putString(Constants.XMPP_USERNAME,
                                        newUsername);
                                editor.putString(Constants.XMPP_PASSWORD,
                                        newPassword);
                                editor.commit();
                                Log
                                        .i(LOGTAG,
                                                "Account registered successfully");
                                xmppManager.runTask();
                            }
                        }
                    }
                };
4) 将监听对象设置到 org.jivesoftware.smack.XMPPConnection 连接对象中:
		connection.addPacketListener(packetListener, packetFilter);
5) 将用户名和密码设置到 Registration 注册包对象中:
		Registration.setType(IQ.Type.SET);
                // registration.setTo(xmppHost);
                // Map<String, String> attributes = new HashMap<String, String>();
                // attributes.put("username", rUsername);
                // attributes.put("password", rPassword);
                // registration.setAttributes(attributes);
                registration.addAttribute("username", newUsername);
                registration.addAttribute("password", newPassword);
6) 发送注册包:
		connection.sendPacket(registration);

LoginTask

1)调用org.jivesoftware.smack.XMPPConnection对象的login函数登陆服务器:

		xmppManager.getConnection().login(
                            xmppManager.getUsername(),
                            xmppManager.getPassword(), XMPP_RESOURCE_NAME);
2)将xmpp连接监听对象设置到org.jivesoftware.smack.XMPPConnection对象:
		if (xmppManager.getConnectionListener() != null) {
                        xmppManager.getConnection().addConnectionListener(
                                xmppManager.getConnectionListener());
                    }
3) 将返回包监听对象设置到 org.jivesoftware.smack.XMPPConnection 对象:
		// packet filter
                    PacketFilter packetFilter = new PacketTypeFilter(
                            NotificationIQ.class);
                    // packet listener
                    PacketListener packetListener = xmppManager
                            .getNotificationPacketListener();
                    connection.addPacketListener(packetListener, packetFilter);
4)如果login产生异常,则重新运行RegisterTask和LoginTask来重新在服务器注册用户名和登陆服务器获取授权。

PersistentConnectionListener

PersistentConnectionListener类从org.jivesoftware.smack.ConnectionListener继承而来,几个主要重载函数:connectionClosed、connectionClosedOnError、reconnectingIn、reconnectionFailed、reconnectionSuccessful。

Androidpn只重载了connectionClosedOnError:

@Override
    public void connectionClosedOnError(Exception e) {
        Log.d(LOGTAG, "connectionClosedOnError()...");
        if (xmppManager.getConnection() != null
                && xmppManager.getConnection().isConnected()) {
            xmppManager.getConnection().disconnect();
        }
        xmppManager.startReconnectionThread();
    }

NotificationPacketListener

NotificationPacketListenerorg.jivesoftware.smack.PacketListener继承而来,主要实现processPacket函数用于处理xmpp返回包:

@Override
    public void processPacket(Packet packet) {
        Log.d(LOGTAG, "NotificationPacketListener.processPacket()...");
        Log.d(LOGTAG, "packet.toXML()=" + packet.toXML());

        if (packet instanceof NotificationIQ) {
            NotificationIQ notification = (NotificationIQ) packet;

            if (notification.getChildElementXML().contains(
                    "androidpn:iq:notification")) {
                String notificationId = notification.getId();
                String notificationApiKey = notification.getApiKey();
                String notificationTitle = notification.getTitle();
                String notificationMessage = notification.getMessage();
                //                String notificationTicker = notification.getTicker();
                String notificationUri = notification.getUri();

                Intent intent = new Intent(Constants.ACTION_SHOW_NOTIFICATION);
                intent.putExtra(Constants.NOTIFICATION_ID, notificationId);
                intent.putExtra(Constants.NOTIFICATION_API_KEY,
                        notificationApiKey);
                intent
                        .putExtra(Constants.NOTIFICATION_TITLE,
                                notificationTitle);
                intent.putExtra(Constants.NOTIFICATION_MESSAGE,
                        notificationMessage);
                intent.putExtra(Constants.NOTIFICATION_URI, notificationUri);
                //                intent.setData(Uri.parse((new StringBuilder(
                //                        "notif://notification.androidpn.org/")).append(
                //                        notificationApiKey).append("/").append(
                //                        System.currentTimeMillis()).toString()));

                xmppManager.getContext().sendBroadcast(intent);
            }
        }

    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值