Сервис Android использует только геттеры - PullRequest
0 голосов
/ 20 июня 2011

Я наконец-то получил образец локальной службы для работы с LocalServiceActivities.java и Основы Android: Часть III - Службы Android .

Вот мой код Controller.java, LocalService.java, Binding.java и ILocalService.java, все они объединяются один за другим, разделенные заголовками комментариев:

/**************************************************************************************************
 * Filename: Controller.java
 * Project name: Local Service Sample
 * Application name: Local Service
 * Description: This file contains the primary activity for this application
 **************************************************************************************************/
package com.marie.localservicesample;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

/*
 * Example of explicitly starting and stopping the local service.
 * This demonstrates the implementation of a service that runs in the same
 * process as the rest of the application, which is explicitly started and stopped
 * as desired.
 */
//public static class Controller extends Activity {
public class Controller extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.local_service_controller);

        // Watch for button clicks.
        Button button = (Button)findViewById(R.id.start);
        button.setOnClickListener(mStartListener);
        button = (Button)findViewById(R.id.stop);
        button.setOnClickListener(mStopListener);
    }

    private OnClickListener mStartListener = new OnClickListener() {
        public void onClick(View v) {
            // Make sure the service is started.  It will continue running
            // until someone calls stopService().  The Intent we use to find
            // the service explicitly specifies our service component, because
            // we want it running in our own process and don't want other
            // applications to replace it.
            //startService(new Intent(Controller.this, LocalService.class));

            Intent startSvc = new Intent(Controller.this, LocalService.class);
            startSvc.putExtra(LocalService.EXTRA_MESSENGER, new Messenger(handler));
            startSvc.putExtra(LocalService.EXTRA_SONG, 7);
            startService(startSvc);

            Intent binding = new Intent(Controller.this, Binding.class);
            startActivity(binding);
        }
    };

    private OnClickListener mStopListener = new OnClickListener() {
        public void onClick(View v) {
            // Cancel a previous call to startService().  Note that the
            // service will not actually stop at this point if there are
            // still bound clients.
            stopService(new Intent(Controller.this,
                    LocalService.class));
        }
    };

    /*
     * This is a handler to be passed to the Service via a Messenger.
     */
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // simple handler test
            String obj = (String) msg.obj;
            Log.i("handleMessge", "obj: " + obj);  
        }
    };
}

/**************************************************************************************************
 * Filename: LocalService.java
 * Project name: Local Service Sample
 * Application name: Local Service
 * Description: This file contains a local service
 **************************************************************************************************/    
package com.marie.localservicesample;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

public class LocalService extends Service {
    private NotificationManager mNM;

    // Unique Identification Number for the Notification.
    // We use it on Notification start, and to cancel it.
    //private int NOTIFICATION = R.string.local_service_started;
    private int NOTIFICATION = R.string.local_service_started;

    private int statusCode = 10;

    // This is the object that receives interactions from clients.  See
    // RemoteService for a more complete example.
    private final IBinder mBinder = new LocalBinder();

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    /**
     * Class for clients to access.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with
     * IPC.
     */
    public class LocalBinder extends Binder implements ILocalService {
        LocalService getService() {
            return LocalService.this;
        }

        @Override
        public int getStatusCode() {
            return statusCode;
        }
    }

    public static final String EXTRA_MESSENGER = "com.marie.localservicesample.EXTRA_MESSENGER";
    private Messenger messenger;

    public static final String EXTRA_SONG = "com.marie.localservicesample.EXTRA_SONG";
    private int song;

    @Override
    public void onCreate() {
        mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);

        // Display a notification about us starting.  We put an icon in the status bar.
        showNotification();

        Thread thr = new Thread(null, new ServiceWorker(), "BackgroundService");
        thr.start();        
    }

    /*
     * This is the ServiceWorker thread that passes messages to the handler defined in
     * the MainActivity class.
     * NOTE: Instead of passing messages to a handler in MainActivity I would like
     * it to pass messages to a handler defined in the RcvMessages activity.
     */
    class ServiceWorker implements Runnable
    {
        public void run() {
            // do background processing here... something simple

            while (messenger == null);

            // send a message to the handler
            try {
                Message msg = Message.obtain();
                msg.obj = "Hello " + "Song " + song;
                msg.arg1 = song;
                messenger.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            } catch (NullPointerException e) {
                e.printStackTrace();
            }

            // stop the service when done...
            // LocalService.this.stopSelf();
            // Or use the unbindBtn in the MainActivity class.
        }
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("LocalService", "Received start id " + startId + ": " + intent);

        Bundle extras = intent.getExtras();

        messenger = (Messenger)extras.get(EXTRA_MESSENGER);
        try {
            song = (Integer) extras.get(EXTRA_SONG);
        } catch (NullPointerException e) {
            e.printStackTrace();
            song = 0;
        }

        // We want this service to continue running until it is explicitly
        // stopped, so return sticky.
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        // Cancel the persistent notification.
        mNM.cancel(NOTIFICATION);

        // Tell the user we stopped.
        Toast.makeText(this, R.string.local_service_stopped, Toast.LENGTH_SHORT).show();
    }

    /**
     * Show a notification while this service is running.
     */
    private void showNotification() {
        // In this sample, we'll use the same text for the ticker and the expanded notification
        CharSequence text = getText(R.string.local_service_started);

        // Set the icon, scrolling text and timestamp
        Notification notification = new Notification(R.drawable.stat_sample, text,
                System.currentTimeMillis());

        // The PendingIntent to launch our activity if the user selects this notification
        //PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, LocalServiceActivities.Controller.class), 0);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, Controller.class), 0);

        // Set the info for the views that show in the notification panel.
        notification.setLatestEventInfo(this, getText(R.string.local_service_label),
                       text, contentIntent);

        // Send the notification.
        mNM.notify(NOTIFICATION, notification);
    }

    /* Duplicate added by Eclipse
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }
    */
}

/**************************************************************************************************
 * Filename: Binding.java
 * Project name: Local Service Sample
 * Application name: Local Service
 * Description: This file contains the binding for this application
 **************************************************************************************************/
package com.marie.localservicesample;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

/*
 * Example of binding and unbinding to the local service.
 * This demonstrates the implementation of a service which the client will
 * bind to, receiving an object through which it can communicate with the service.
 */
public class Binding extends Activity {
    private boolean mIsBound;

    private LocalService mBoundService;

    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            // This is called when the connection with the service has been
            // established, giving us the service object we can use to
            // interact with the service.  Because we have bound to a explicit
            // service that we know is running in our own process, we can
            // cast its IBinder to a concrete class and directly access it.
            mBoundService = ((LocalService.LocalBinder)service).getService();

            ILocalService localService = (ILocalService)service;
            int statusCode = localService.getStatusCode();

            Log.d("Binding","called onServiceConnected. statusCode: " + statusCode);

            Toast.makeText(Binding.this, R.string.local_service_connected,
                    Toast.LENGTH_SHORT).show();
        }

        public void onServiceDisconnected(ComponentName className) {
            // This is called when the connection with the service has been
            // unexpectedly disconnected -- that is, its process crashed.
            // Because it is running in our same process, we should never
            // see this happen.
            mBoundService = null;

            Log.d("Binding", "called onServiceDisconnected");

            Toast.makeText(Binding.this, R.string.local_service_disconnected,
                    Toast.LENGTH_SHORT).show();
        }
    };

    void doBindService() {
        // Establish a connection with the service.  We use an explicit
        // class name because we want a specific service implementation that
        // we know will be running in our own process (and thus won't be
        // supporting component replacement by other applications).
        bindService(new Intent(Binding.this, 
                LocalService.class), mConnection, Context.BIND_AUTO_CREATE);
        mIsBound = true;
    }

    void doUnbindService() {
        if (mIsBound) {
            // Detach our existing connection.
            unbindService(mConnection);
            mIsBound = false;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        doUnbindService();
    }

    private OnClickListener mBindListener = new OnClickListener() {
        public void onClick(View v) {
            doBindService();
        }
    };

    private OnClickListener mUnbindListener = new OnClickListener() {
        public void onClick(View v) {
            doUnbindService();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.local_service_binding);

        // Watch for button clicks.
        Button button = (Button)findViewById(R.id.bind);
        button.setOnClickListener(mBindListener);
        button = (Button)findViewById(R.id.unbind);
        button.setOnClickListener(mUnbindListener);
    }
}

/**************************************************************************************************
 * Filename: ILocalService.java
 * Project name: Local Service Sample
 * Application name: Local Service
 * Description: This file contains an example interface for LocalService
 **************************************************************************************************/

package com.marie.localservicesample;

public interface ILocalService {

    // An example method for ILocalService
    public int getStatusCode();

}

Мой вопрос: зачем кому-то предоставлять ILocalService.java, если у них уже есть startService () с потоком и обработчиком, как у меня? Мой ILocalService.java является тривиальной демонстрацией, которая запрашивает код состояния. Насколько я могу судить, мой ILocalService.java будет состоять только из получателей статуса и без установщиков. Так я буду спрашивать только информацию о статусе моей местной службы? Что может быть примером сеттера для моего локального сервиса?

1 Ответ

1 голос
/ 20 июня 2011

Ваш переплет выглядит так:

public class LocalBinder extends Binder implements ILocalService {
        LocalService getService() {
            return LocalService.this;
        }

        @Override
        public int getStatusCode() {
            return statusCode;
        }
    }

Ключевая часть интереса - getService. Это означает, что любая из ваших Деятельностей, которые связаны с вашей Службой (поскольку это локальная служба), может фактически получить объект службы и может вызывать ЛЮБЫЕ функции для этой функции службы, а не только получатели. Вы не ограничены только узким каналом связи startService и Intent, у вас есть полный интерфейс метода для сервисного объекта. В прошлом я передавал BluetoothDevice экземпляры, Handler экземпляры и другие сложные Java-объекты через сервисный объект.

...