My LocalService.java содержит класс LocalBinder
, который определяет методы, объявленные в ILocalService.java , чьи определения загромождают мои LocalService.java ,Я хотел бы переместить его в свой собственный файл LocalBinder.java .Вот мой LocalBinder
:
public class LocalBinder extends Binder implements ILocalService {
@Override
public LocalService getService() {
return LocalService.this;
}
@Override
public int getStatusCode() {
return statusCode;
}
@Override
public void startRcvThread(Handler handler) {
Thread thread = passHandlerToThread(handler);
thread.start();
}
}
Я пробовал несколько раз и потерпел неудачу.Не лучше ли мне оставить LocalBinder
в LocalService
?
Ниже приведены все пять файлов исходного кода, помеченных комментариями заголовков.Пожалуйста, посмотрите на заголовок моего вопроса.Это объясняет, что я хочу сделать.Я хочу снять загромождение моего LocalService.java, удалив «public class LocalBinder» из LocalService.java и поместив его в свой собственный файл: LocalBinder.java.Любая помощь очень ценится.@Commonsware уже оказал значительную помощь, но мне немного сложно понять.
/**************************************************************************************************
* 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 {
// Message types sent from the BluetoothReadService Handler
public static final int MESSAGE_SONG = 1;
public static final int MESSAGE_NOTHING = 2;
@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(ctrlHandler));
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));
}
};
/*
* Here's a way to send a message to a handler - haven't tried it yet:
* Give the new state to the Handler so the UI Activity can update
* mHandler.obtainMessage(BlueSentry.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
* But for now let's msg.what to our handler
*/
private Handler ctrlHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case MESSAGE_SONG:
String songObj = (String) msg.obj;
int songArg1 = msg.arg1;
Log.i("ctrlHandler", "MESSAGE_SONG: " + songObj + " " + songArg1);
break;
case MESSAGE_NOTHING:
String nothingObj = (String) msg.obj;
int nothingArg1 = msg.arg1;
Log.i("ctrlHandler", "MESSAGE_NOTHING: " + nothingObj + " " + nothingArg1);
break;
default:
break;
}
}
};
}
/**************************************************************************************************
* 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.Handler;
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 = 99;
private int emptyMsg = 549;
// 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 {
@Override
public LocalService getService() {
return LocalService.this;
}
@Override
public int getStatusCode() {
return statusCode;
}
@Override
public void startRcvThread(Handler handler) {
Thread thread = passHandlerToThread(handler);
thread.start();
}
}
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();
/* Move this stuff to afterStartCommand()
Thread thr = new Thread(null, new ServiceWorker(), "LocalService");
thr.start();
*/
}
// Call this at the end of onStartCommand()
public void afterStartCommand() {
Thread thr = new Thread(null, new ServiceWorker(), "LocalService");
thr.start();
}
/*
* see http://developer.android.com/reference/java/lang/Thread.html
*/
class threadClass extends Thread {
private Handler mHandler;
private Message mMsg;
// constructor
public threadClass(Handler handler, Message msg) {
// do something like save the Handler reference
mHandler = handler;
mMsg = msg;
}
@Override
public void run() {
// do some background processing, call the Handler?
mHandler.sendMessage(mMsg);
}
}
public Thread passHandlerToThread(Handler handler) {
handler.sendEmptyMessage(emptyMsg);
Message msg = Message.obtain();
msg.what = emptyMsg;
Thread thread = new threadClass(handler, msg);
return thread;
}
/*
* This is the ServiceWorker thread that passes messages to the handler defined in
* the Controller activity.
*/
class ServiceWorker implements Runnable
{
public void run() {
// do background processing here... something simple
while (messenger == null) {
try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
}
// send a message to the handler
try {
Message msg = Message.obtain();
msg.what = Controller.MESSAGE_SONG;
msg.obj = "Song";
msg.arg1 = song;
messenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
try {
Message msg = Message.obtain();
msg.what = Controller.MESSAGE_NOTHING;
msg.obj = "Nothing";
msg.arg1 = 0;
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;
}
afterStartCommand();
// 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);
}
}
/**************************************************************************************************
* 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 ILocalService mBoundService = null;
private LocalService mBoundService1;
private LocalService mBoundService2;
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.
mBoundService1 = ((LocalService.LocalBinder)service).getService();
ILocalService localSvc = (ILocalService)service;
mBoundService2 = localSvc.getService();
if (mBoundService1 == mBoundService2) {
Log.d("mBoundeService 1 and 2 ", "are equal");
mBoundService = (ILocalService) service;
}
int statusCode = localSvc.getStatusCode();
Log.d("Binding.java","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.
mBoundService1 = null;
mBoundService2 = 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) {
LocalService service = mBoundService.getService();
if (service != null) Log.d("doUnbindService", "service: " + service);
int statusCode = mBoundService.getStatusCode();
if (statusCode != 0) Log.d("doUnbindService", "statusCode: " + statusCode);
// 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();
Intent rcvMsg = new Intent(Binding.this, RcvMessages.class);
startActivity(rcvMsg);
}
};
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: RcvMessages.java
* Project name: Local Service Sample
* Application name: Local Service
* Description: This file contains stub code that displays a test message in an EditText.
**************************************************************************************************/
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.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.text.InputType;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
/*
* Class: RcvMessages
* Purpose: RcvMessages is stub code that I want to extend in some way to receive messages from
* the background Service.
*/
public class RcvMessages extends Activity {
//private LocalService mBoundService;
private boolean mIsBound;
private ILocalService mBoundService;
//public static final String EXTRA_SONG = "com.marie.mainactivity.EXTRA_SONG";
EditText myText;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//mBoundService = ((LocalService.LocalBinder)service).getService();
mBoundService = (ILocalService)service;
ILocalService localSvc = (ILocalService)service;
int statusCode = localSvc.getStatusCode();
Log.d("RcvMessages.java","called onServiceConnected. statusCode: " + statusCode);
//myText.setText("statusCode: " + statusCode);
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
};
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(RcvMessages.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();
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.messages);
myText = (EditText)findViewById(R.id.my_text);
myText.setSingleLine();
myText.setInputType(InputType.TYPE_NULL);
// Display a simple test message for now.
// myText.setText("RcvMessages here");
Button button = (Button)findViewById(R.id.display);
button.setOnClickListener(mDisplayListener);
// I'm expecting this to call mConnection()'s onServiceConnected
// bindService(new Intent(RcvMessages.this, LocalService.class), mConnection, Context.BIND_AUTO_CREATE);
// IBinder binder = mBoundService.onBind(new Intent(RcvMessages.this, LocalService.class));
doBindService();
}
private OnClickListener mDisplayListener = 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));
mBoundService.startRcvThread(rcvHandler);
}
};
/*
@Override
public void onStart(){
super.onStart();
Bundle extras = getIntent().getExtras();
int song = (Integer) extras.get(EXTRA_SONG);
//myText.setText("song " + song);
// Start the background Service for sending canned messages to the handler as a test.
Log.d("RcvMessages", "starting service from rcvmessages");
Intent localSvc = new Intent(RcvMessages.this, LocalService.class);
localSvc.putExtra(LocalService.EXTRA_MESSENGER, new Messenger(handler));
localSvc.putExtra(EXTRA_SONG, song);
startService(localSvc);
}
*/
/*
* This is a handler to be passed to the local Service.
*/
private Handler rcvHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
int what = msg.what;
Log.i("rcvHandler", "rcvWhat: " + what);
myText.setText("rcvWhat: " + what);
}
};
}
/**************************************************************************************************
* 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;
import android.os.Handler;
public interface ILocalService {
public LocalService getService();
public int getStatusCode();
public void startRcvThread(Handler handler);
}