0

私のアプリの構造は、バックグラウンドで実行されているサービスで構成されていますプッシュメッセージをリッスンし、これらのメッセージを転送してDBに挿入し、通知として表示するか、チャッターのチャットウィンドウが開いていてフロントスクリーンにある場合はチャットアクティビティに送信します聞いている放送受信機。

次の画像は、私のアプリのチャットの構造とワークフローを説明しています(アルファベット順に従ってください) ここに画像の説明を入力


チャット ウィンドウ アクティビティのコードは次のとおりです。

this.service = new ServiceManager(this, PushService.class,
                new Handler() {
                    @Override
                    public void handleMessage(Message msg) {
                        // Receive message from service
                        switch (msg.what) {
                        case 10:

                        reloadMessagesInTheChat();
                                                     // Play sound
                        if (mp.isPlaying())
                            mp.stop();
                        mp.start();
                        break;

                    default:
                        showErrorMsssage("Some messages arrived");
                        super.handleMessage(msg);
                        break;
                    }
                }
            });


    this.service.start();

            // Now sending the message (I do it initially to tell the service which user is in the chat now, such that it forwards messages to this receiver, instead of creating notifications)
    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            try {
                service.send(Message.obtain(null, 10, user_id, 0));
            } catch (RemoteException e) {
                e.printStackTrace();
                                    // This is just a Toast Message:
                showErrorMsssage("Couldn't send messages to the service");
            }
        }
    }, 1000);

サービスのコードは次のとおりです。

まず、これはメッセージをルーティングする条件です

if(connectedChatUser != ChatUserInTheReceivedMessage ){
    // Create Notification with Pending Intent to open chat windows with the user
}
else{
      send(Message.obtain(null, 10,  "ID_OF_THE_CHATTER"  , 0));
}

サービスの重要な部分は次のとおりです。

    ArrayList<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track of all current registered clients.
    final Messenger mMessenger = new Messenger(new IncomingHandler()); // Target we publish for clients to send messages to IncomingHandler.

    private class IncomingHandler extends Handler { 
// Handler of incoming messages from clients.
        @Override
        public void handleMessage(Message msg) {

            switch (msg.what) {
            case MSG_REGISTER_CLIENT:
                mClients.add(msg.replyTo);
                break;
            case MSG_UNREGISTER_CLIENT:
                mClients.remove(msg.replyTo);
                break;            
            default:
                //super.handleMessage(msg);
                onReceiveMessage(msg);
            }
        }
    }



    private int connectedChatUser = 0;
    private int contactList = 0;


        /*@Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            return START_STICKY; // run until explicitly stopped.
        }*/


        @Override
        public IBinder onBind(Intent intent) {
            return mMessenger.getBinder();
        }


    protected void send(Message msg) {
     for (int i=mClients.size()-1; i>=0; i--) {
            try {
               mClients.get(i).send(msg);
            }
            catch (RemoteException e) {
                // The client is dead. Remove it from the list; we are going through the list from back to front so this is safe to do inside the loop.
                mClients.remove(i);
            }
        }       
   }

これは、開いているチャット ウィンドウの ID を最初に受け取る Service の Receiver です。

public void onReceiveMessage(Message msg) {
        if (msg.what == CHAT_USER) {
                // User ID sent from the activity initially
            connectedChatUser = msg.arg1;
        }
            // Other cases aren't important as they cause no problem 

      }

最後に、アクティビティ内のサービスは、このクラスのインスタンスです。

public class ServiceManager {
    private Class<? extends PushService> mServiceClass;
    private Context mActivity;
    private boolean mIsBound;
    private Messenger mService = null;
    private Handler mIncomingHandler = null;
    private final Messenger mMessenger = new Messenger(new IncomingHandler());

    private class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            if (mIncomingHandler != null) {
                if(GlobalSettings.dev)Log.i("ServiceHandler", "Incoming message. Passing to handler: "+msg);
                mIncomingHandler.handleMessage(msg);
            }
        }
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            mService = new Messenger(service);
            //textStatus.setText("Attached.");
            if(GlobalSettings.dev)Log.i("ServiceHandler", "Attached.");
            try {
                Message msg = Message.obtain(null, AbstractService.MSG_REGISTER_CLIENT);
                msg.replyTo = mMessenger;
                mService.send(msg);
            } catch (RemoteException e) {
                // In this case the service has crashed before we could even do anything with it
            }
        }

        public void onServiceDisconnected(ComponentName className) {
            // This is called when the connection with the service has been unexpectedly disconnected - process crashed.
            mService = null;
            //textStatus.setText("Disconnected.");
            if(GlobalSettings.dev)Log.i("ServiceHandler", "Disconnected.");
        }
    };

    public ServiceManager(Context context, Class<? extends PushService> serviceClass, Handler incomingHandler) {
        this.mActivity = context;
        this.mServiceClass = serviceClass;
        this.mIncomingHandler = incomingHandler;

        if (isRunning()) {
            doBindService();
        }
    }

    public void start() {
        doStartService();
        doBindService();
    }

    public void stop() {
        doUnbindService();
        doStopService();        
    }

    /**
     * Use with caution (only in Activity.onDestroy())! 
     */
    public void unbind() {
        doUnbindService();
    }

    public boolean isRunning() {
        ActivityManager manager = (ActivityManager) mActivity.getSystemService(Context.ACTIVITY_SERVICE);

        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (mServiceClass.getName().equals(service.service.getClassName())) {
                return true;
            }
        }

        return false;
    }

    public void send(Message msg) throws RemoteException {
        if (mIsBound) {
            if (mService != null) {
                mService.send(msg);
            }
        }
        else{
            if(GlobalSettings.dev)Log.d("From Activity to service:","Failed as it's not bound");
        }
    }

    private void doStartService() {
        mActivity.startService(new Intent(mActivity, mServiceClass));       
    }

    private void doStopService() {
        mActivity.stopService(new Intent(mActivity, mServiceClass));
    }

    private void doBindService() {
        mActivity.bindService(new Intent(mActivity, mServiceClass), mConnection, Context.BIND_AUTO_CREATE);
        mIsBound = true;
    }

    private void doUnbindService() {
        if (mIsBound) {
            // If we have received the service, and hence registered with it, then now is the time to unregister.
            if (mService != null) {
                try {
                    Message msg = Message.obtain(null, AbstractService.MSG_UNREGISTER_CLIENT);
                    msg.replyTo = mMessenger;
                    mService.send(msg);
                } catch (RemoteException e) {
                    // There is nothing special we need to do if the service has crashed.
                }
            }

            // Detach our existing connection.
            mActivity.unbindService(mConnection);
            mIsBound = false;
            //textStatus.setText("Unbinding.");
            if(GlobalSettings.dev)Log.i("ServiceHandler", "Unbinding.");
        }
    }
}
4

1 に答える 1

0

まあ、あまり複雑にならなくても、私の問題は、アクティビティが一時停止されているときに、サービスのバインドを解除するコードがないことです。

onPause と onDestroy のバインドを解除し、onResume を再度バインドするための適切なコードを追加しました。

以上です

于 2013-01-05T02:49:22.763 に答える