Я наконец-то получил образец локальной службы для работы с 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 будет состоять только из получателей статуса и без установщиков. Так я буду спрашивать только информацию о статусе моей местной службы? Что может быть примером сеттера для моего локального сервиса?