Android的新手,试图弄清楚服务。我正在尝试将服务绑定到一个活动,我正在遵循文档中的示例,但我在下面标记的行(appService.playSong(title))上不断收到NullPointerException。在调试器中检查它会发现appService确实为null。
public class Song extends Activity implements OnClickListener,Runnable {
protected static int currentPosition;
private ProgressBar progress;
private TextView songTitle;
private MPService appService;
private ServiceConnection onService = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder rawBinder) {
appService = ((MPService.LocalBinder)rawBinder).getService();
}
public void onServiceDisconnected(ComponentName classname) {
appService = null;
}
};
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.song);
Intent bindIntent = new Intent(Song.this,MPService.class);
bindService(bindIntent,onService,
Context.BIND_AUTO_CREATE);
Bundle b = getIntent().getBundleExtra("songdata");
String title = b.getString("song title");
// ...
appService.playSong(title); // nullpointerexception
// ...
}
以下是该服务的相关部分:
package org.example.music;
// imports
public class MPService extends Service {
private MediaPlayer mp;
public static int currentPosition = 0;
public List<String> songs = new ArrayList<String>();
public static String songTitle;
private static final String MEDIA_PATH = new String("/mnt/sdcard/");
@Override
public void onCreate() {
super.onCreate();
mp = new MediaPlayer();
songs = Music.songs;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
public class LocalBinder extends Binder {
MPService getService() {
return MPService.this;
}
}
private final IBinder binder = new LocalBinder();
@Override
public IBinder onBind(Intent intent) {
return binder;
}
public void playSong(String songPath) {
try {
mp.reset();
mp.setDataSource(songPath);
mp.prepare();
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer arg0) {
nextSong();
}
});
songTitle = songPath.substring(12,songPath.length()-4);
} catch (IOException e) {
Log.v(getString(R.string.app_name),e.getMessage());
}
}
public void nextSong() {
if (++currentPosition >= songs.size()) {
currentPosition = 0;
}
String song = MEDIA_PATH+songs.get(currentPosition);
playSong(song);
}
public void prevSong() {
if (--currentPosition<0) {
currentPosition=songs.size()-1;
}
String song = Music.MEDIA_PATH+songs.get(currentPosition);
playSong(song);
}
public int getSongPosition() {
return mp.getCurrentPosition();
}
public MediaPlayer getMP() {
return mp;
}
}
我在AndroidManifest.xml中注册了该服务,并设置了android:enabled =“true”。你在这看到任何明显的错误吗?
答案 0 :(得分:1)
您可以制作本地和远程两种绑定。本地仅供您的应用程序和远程使用,以供任何实现特定接口的应用程序使用。 你应该从本地绑定开始。
Local binding tutorial。
Remote binding tutorial
我没有绑定的解决方案:
public class MyActivity extends Activity{
@Override
public void onCreate(Bundle savedInstanceState){
...
Intent it = new Intent(MyService.ACTIVITY_START_APP);
it.setClass(getApplicationContext(), MyService.class);
startService(it);
}
...
@Override
protected void onResume() {
super.onResume();
registerBroadcastReceiver();
}
@Override
protected void onPause() {
super.onPause();
this.unregisterReceiver(this.receiver);
}
...
private BroadcastReceiver receiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(MyService.BROADCAST_INIT)) {
//do your stuff here after init
}
}
};
private void registerBroadcastReceiver(){
IntentFilter filter = new IntentFilter();
filter.addAction(HMyService.BROADCAST_INIT);
this.registerReceiver(receiver, filter);
}
}
您的服务:
public class MyService extends Service{
public static final String BROADCAST_INITIAL_DATA = "org.myapp.BROADCAST_INIT";
public static final String ACTIVITY_START_APP = "org.myapp.ACTIVITY_START_APP";
@Override
public int onStartCommand (Intent intent, int flags, int startId){
super.onStartCommand(intent, flags, startId);
if(intent.getAction().equals(ACTIVITY_START_APP)){
//do your initialization
//inform the client/GUI
Intent i = new Intent();
i.setAction(BROADCAST_INIT);
sendBroadcast(i);
}else{
//some other stuff like handle buttons
}
}
}
祝你好运。
答案 1 :(得分:1)
您假设bindService()将同步连接到服务,但只有在onCreate()finshed之后才能使用该连接。
框架在UI线程上运行onCreate(),而bindService()只是记下以便稍后连接到服务。连接到服务将始终在UI线程上完成,因此这只能在执行onCreate之后进行。在onCreate()之后,您甚至无法依赖正在建立的连接。它会发生在那之后的某个时间:)。此外,框架可能会断开服务的意愿,尽管它应该只在低内存条件下发生。
因此,将使用appService的代码从onCreate()移动到onServiceConnected(),它就可以工作了。
答案 2 :(得分:0)
从快速浏览一下,看起来您在绑定完成之前尝试访问您的服务。在尝试调用服务上的任何方法之前,您必须确保onServiceConnected
已被解雇。
示例:
Intent bindIntent = new Intent(Song.this,MPService.class);
bindService(bindIntent,onService, Context.BIND_AUTO_CREATE);
//Wait until service has bound
while(appService == null){
Thread.sleep(100);
}
appService.playSong(title);
此示例不是最佳示例,但它表明您必须等到绑定完成后再尝试访问该服务。