fr.mixit.android.ui.fragments.BoundServiceDialogFragment.java Source code

Java tutorial

Introduction

Here is the source code for fr.mixit.android.ui.fragments.BoundServiceDialogFragment.java

Source

/*
 * Copyright 2011 - 2013 Mathieu Calba
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package fr.mixit.android.ui.fragments;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.util.Log;

import com.actionbarsherlock.app.SherlockDialogFragment;

import fr.mixit.android.MixItApplication;
import fr.mixit.android.services.MixItService;
import fr.mixit.android.ui.fragments.BoundServiceFragment.BoundServiceContract;

public abstract class BoundServiceDialogFragment extends SherlockDialogFragment {

    protected static final boolean DEBUG_MODE = MixItApplication.DEBUG_MODE;
    public static final String TAG = BoundServiceDialogFragment.class.getSimpleName();

    /** Flag indicating whether we have called bind on the mService. */
    protected boolean mIsBound = false;
    /**
     * Flag indicating whether the mService is bound and we have registered to it.
     */
    protected boolean mServiceReady = false;

    /** Messenger for communicating with mService. */
    protected Messenger mService = null;

    /**
     * Handler of incoming messages from mService.
     */
    @SuppressLint("HandlerLeak")
    protected class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MixItService.MSG_REGISTER_CLIENT:
                onServiceReady();
                break;
            case MixItService.MSG_UNREGISTER_CLIENT:
                onServiceNotReady();
                break;
            default:
                if (DEBUG_MODE) {
                    Log.d(TAG, "onMessageReceivedFromService(): What:" + msg.what + " - Status:" + msg.arg1);
                }
                onMessageReceivedFromService(msg);
            }
        }
    }

    /**
     * Target we publish for clients to send messages to IncomingHandler.
     */
    final Messenger mMessenger = new Messenger(new IncomingHandler());

    /**
     * Class for interacting with the main interface of the mService.
     */
    private final ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder aService) {
            // This is called when the connection with the mService has been established, giving us the mService object we can use to interact with the
            // mService. We are communicating with our mService through an IDL interface, so get a client-side representation of that from the raw mService
            // object.
            mService = new Messenger(aService);

            // We want to monitor the mService for as long as we are connected to it.
            try {
                final Message msg = Message.obtain(null, MixItService.MSG_REGISTER_CLIENT);
                msg.replyTo = mMessenger;
                mService.send(msg);
            } catch (final RemoteException e) {
                // In this case the mService has crashed before we could even do anything with it; we can count on soon being disconnected (and then reconnected
                // if it can be restarted) so there is no need to do anything here.
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName className) {
            // This is called when the connection with the mService has been unexpectedly disconnected -- that is, its process crashed.
            mService = null;
        }
    };

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        try {
            @SuppressWarnings("unused")
            final BoundServiceContract contract = (BoundServiceContract) activity;
        } catch (final ClassCastException e) {
            throw new ClassCastException(
                    activity.toString() + " must implement " + BoundServiceContract.class.getName());
        }
    }

    @Override
    public void onStart() {
        super.onStart();

        doBindService();
    }

    @Override
    public void onStop() {
        super.onStop();

        doUnbindService();
    }

    protected void doBindService() {
        if (DEBUG_MODE) {
            Log.d(TAG, "doBindService()");
        }
        // Establish a connection with the mService. We use an explicit class name because there is no reason to be able to let other applications replace our
        // component.
        if (getActivity() == null || isDetached()) {
            if (DEBUG_MODE) {
                Log.d(TAG,
                        "Fragment is detached from hos activity or getActivity is null, so impossible to bind service");
            }
            return;
        }
        getActivity().bindService(new Intent(getActivity(), MixItService.class), mConnection,
                Context.BIND_AUTO_CREATE);
        mIsBound = true;
    }

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

            // Detach our existing connection.
            if (getActivity() == null || isDetached()) {
                if (DEBUG_MODE) {
                    Log.d(TAG,
                            "Fragment is detached from hos activity or getActivity is null, so impossible to unbind service");
                }
            } else {
                getActivity().unbindService(mConnection);
            }
            mIsBound = false;
        }
    }

    /**
     * When the mService is bound and we are registered to it, we refresh the Data from WebService with the {@link MixItService}
     */
    protected void onServiceReady() {
        mServiceReady = true;
    }

    /**
     * Called when a message other than register and unregister is received from the mService. Be careful, you need to treat the information, and refresh UI
     * before calling the super method.
     * 
     * @param msg the message received from the mService
     */
    abstract protected void onMessageReceivedFromService(Message msg);

    /**
     * Called when the parent activity is no longer registered to this mService, ergo the mService won't treat possible request from us
     */
    protected void onServiceNotReady() {
        mServiceReady = false;
    }

    protected void setRefreshMode(boolean state) {
        if (getActivity() != null && !isDetached()) {
            ((BoundServiceContract) getActivity()).setRefreshMode(state);
        }
    }

    protected void restartLoader(int id, Bundle args, LoaderCallbacks<Cursor> callback) {
        if (getActivity() == null || isDetached()) {
            return;
        }
        getLoaderManager().restartLoader(id, args, callback);
    }

}