在绑定服务器

时间:2016-03-17 22:00:51

标签: android service

我已经在这个圈子里绕了好几天。我正在按照教程创建音乐播放器服务: part 2 of music player tutorial

我认为我已经正确地遵循了它,但是在尝试设置歌曲ID时出现错误,因为该服务尚未正确启动。检查它永远不会调用MusicService类的onBind方法。通常这是由于没有在android清单中正确设置服务。但是,我查看了许多帮助页面,相应地更改了我的服务电话,而且我不认为它是错误的来源。我有什么想法吗?

Android清单:          

    <uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:launchMode="singleTop"
            android:screenOrientation="portrait" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

    <service android:name="mycompany.mediaplayer.MusicService">
    </service>

</manifest>

MainActivity.java

package mycompany.mediaplayer;

import android.provider.BaseColumns;
import android.provider.UserDictionary;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

import android.os.IBinder;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.view.MenuItem;
import android.view.View;
import mycompany.mediaplayer.MusicService.MusicBinder;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import android.net.Uri;
import android.content.ContentResolver;
import android.database.Cursor;
import android.widget.ListView;

public class MainActivity extends ActionBarActivity {

    private ArrayList<Song> songList;
    private ListView songView;
    private MusicService musicSrv;
    private Intent playIntent;
    private boolean musicBound=false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        songView = (ListView)findViewById(R.id.song_list);
        songList = new ArrayList<Song>();
        getSongList();
        Collections.sort(songList, new Comparator<Song>(){
            public int compare(Song a, Song b){
                return a.getTitle().compareTo(b.getTitle());
            }
        });
        SongAdapter songAdt = new SongAdapter(this, songList);
        songView.setAdapter(songAdt);
    }

    //connect to the service
    private ServiceConnection musicConnection = new ServiceConnection(){

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            MusicBinder binder = (MusicBinder)service;
            //get service
            musicSrv = binder.getService();
            //pass list
            musicSrv.setList(songList);
            musicBound = true;
            Log.i("onServiceConnected", "Have called connection");
            Log.i("onServiceConnected", String.valueOf(musicSrv));
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            musicBound = false;
        }
    };

    @Override
    protected void onStart() {
        super.onStart();
        if(playIntent==null){
            Log.i("onStart", "Binding service");
            playIntent = new Intent(this, MusicService.class);
            Log.i("onStart", "Play intent "+String.valueOf(playIntent));
            Log.i("onStart", String.valueOf(bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE)));
            startService(playIntent);
        }
        Log.i("onStart", "Have started the activity");
        Log.i("onStart", String.valueOf(musicSrv));
    }

    @Override
    protected void onDestroy() {
        stopService(playIntent);
        musicSrv=null;
        super.onDestroy();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

//        //noinspection SimplifiableIfStatement
//        if (id == R.id.action_settings) {
//            return true;
//        }
        switch (item.getItemId()) {
            case R.id.action_shuffle:
                //shuffle
                break;
            case R.id.action_end:
                stopService(playIntent);
                musicSrv=null;
                System.exit(0);
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    public void songPicked(View view){
        Log.i("songPicked", String.valueOf(musicSrv));
        Log.i("songPicked", String.valueOf(Integer.parseInt(view.getTag().toString())));
        int song_number = Integer.parseInt(view.getTag().toString());
        Log.i("songPicked", String.valueOf(song_number));
        musicSrv.setSong(song_number);
        musicSrv.playSong();
    }

    public void getSongList() {
        //retrieve song info
        ContentResolver musicResolver = getContentResolver();

        Uri musicUri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
        Cursor musicCursor = musicResolver.query(musicUri, null, null, null, null);
        Log.i("MusicRetriever", "Query finished. " + (musicCursor == null ? "Returned NULL." : "Returned a cursor."));
        if(musicCursor!=null && musicCursor.moveToFirst()){
            //get columns
            int titleColumn = musicCursor.getColumnIndex
                    (android.provider.MediaStore.Audio.Media.TITLE);
            int idColumn = musicCursor.getColumnIndex
                    (android.provider.MediaStore.Audio.Media._ID);
            int artistColumn = musicCursor.getColumnIndex
                    (android.provider.MediaStore.Audio.Media.ARTIST);
            //add songs to list
            do {
                long thisId = musicCursor.getLong(idColumn);
                String thisTitle = musicCursor.getString(titleColumn);
                String thisArtist = musicCursor.getString(artistColumn);
                songList.add(new Song(thisId, thisTitle, thisArtist));
                //Log.i("MusicRetriever", "Added song" + thisTitle);
            }
            while (musicCursor.moveToNext());
        }
    }
}

MusicService.java

package mycompany.mediaplayer;

/**
 * Created by Neill on 28/02/2016.
 */

import java.util.ArrayList;

import android.app.Service;
import android.content.ContentUris;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.os.PowerManager;
import android.util.Log;

public class MusicService extends Service implements
        MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener,
        MediaPlayer.OnCompletionListener {

    //media player
    private MediaPlayer player;
    //song list
    private ArrayList<Song> songs;
    //current position
    private int songPosn;
    private final IBinder musicBind = new MusicBinder();

    public void onCreate(){
        //create the service
        super.onCreate();
        //initialize position
        songPosn=0;
        //create player
        Log.i("onCreate", "Creating service");
        player = new MediaPlayer();
        initMusicPlayer();
    }

    public void onCompletion(MediaPlayer mp) {
    }

    public boolean onError(MediaPlayer mp, int a, int b) {
        return false;
    }

    public void initMusicPlayer(){
        //set player properties
        player.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
        player.setAudioStreamType(AudioManager.STREAM_MUSIC);
        player.setOnPreparedListener(this);
        player.setOnCompletionListener(this);
        player.setOnErrorListener(this);
    }

    public void setList(ArrayList<Song> theSongs){
        songs=theSongs;
    }

    public class MusicBinder extends Binder {
        MusicService getService() {
            return MusicService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.i("onBind", "Returning bind");
        return musicBind;
    }

    @Override
    public boolean onUnbind(Intent intent){
        player.stop();
        player.release();
        return false;
    }
    public void playSong(){
        //play a song
        player.reset();
        //get song
        Song playSong = songs.get(songPosn);
        //get id
        long currSong = playSong.getID();
        //set uri
        Uri trackUri = ContentUris.withAppendedId(
                android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                currSong);
        try{
            player.setDataSource(getApplicationContext(), trackUri);
        }
        catch(Exception e){
            Log.e("MUSIC SERVICE", "Error setting data source", e);
        }
        player.prepareAsync();
    }

    @Override
    public void onPrepared(MediaPlayer mp) {
        //start playback
        mp.start();
    }

    public void setSong(int songIndex){
        songPosn=songIndex;
    }

}

最后是logcat:

03-17 21:55:43.986 29835-29835/? I/art: Late-enabling -Xcheck:jni
03-17 21:55:44.028 29835-29835/? W/ResourceType: Found multiple library tables, ignoring...
03-17 21:55:44.034 29835-29835/? W/ResourceType: Found multiple library tables, ignoring...
03-17 21:55:44.038 29835-29835/? W/ResourceType: Found multiple library tables, ignoring...
03-17 21:55:44.243 29835-29835/mycompany.mediaplayer I/MusicRetriever: Query finished. Returned a cursor.
03-17 21:55:44.308 29835-29835/mycompany.mediaplayer I/onStart: Binding service
03-17 21:55:44.308 29835-29835/mycompany.mediaplayer I/onStart: Play intent Intent { cmp=mycompany.mediaplayer/.MusicService }
03-17 21:55:44.310 29835-29835/mycompany.mediaplayer I/onStart: false
03-17 21:55:44.310 29835-29835/mycompany.mediaplayer I/onStart: Have started the activity
03-17 21:55:44.310 29835-29835/mycompany.mediaplayer I/onStart: null
03-17 21:55:44.322 29835-29864/mycompany.mediaplayer D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
03-17 21:55:44.337 29835-29835/mycompany.mediaplayer D/Atlas: Validating map...
03-17 21:55:44.399 29835-29864/mycompany.mediaplayer I/Adreno-EGL: <qeglDrvAPI_eglInitialize:410>: EGL 1.4 QUALCOMM build: AU_LINUX_ANDROID_LA.BF.1.1.1_RB1.05.01.00.042.030_msm8226_LA.BF.1.1.1_RB1__release_AU ()
                                                                   OpenGL ES Shader Compiler Version: E031.25.03.06
                                                                   Build Date: 06/10/15 Wed
                                                                   Local Branch: 
                                                                   Remote Branch: quic/LA.BF.1.1.1_rb1.24
                                                                   Local Patches: NONE
                                                                   Reconstruct Branch: AU_LINUX_ANDROID_LA.BF.1.1.1_RB1.05.01.00.042.030 + 6151be1 +  NOTHING
03-17 21:55:44.401 29835-29864/mycompany.mediaplayer I/OpenGLRenderer: Initialized EGL, version 1.4
03-17 21:55:44.421 29835-29864/mycompany.mediaplayer D/OpenGLRenderer: Enabling debug mode 0
03-17 21:55:44.780 29835-29835/mycompany.mediaplayer I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@285dcbce time:12224185
03-17 21:55:46.802 29835-29835/mycompany.mediaplayer I/songPicked: null
03-17 21:55:46.802 29835-29835/mycompany.mediaplayer I/songPicked: 6
03-17 21:55:46.802 29835-29835/mycompany.mediaplayer I/songPicked: 6
03-17 21:55:46.803 29835-29835/mycompany.mediaplayer D/AndroidRuntime: Shutting down VM
03-17 21:55:46.804 29835-29835/mycompany.mediaplayer E/AndroidRuntime: FATAL EXCEPTION: main
                                                                       Process: mycompany.mediaplayer, PID: 29835
                                                                       java.lang.IllegalStateException: Could not execute method of the activity
                                                                           at android.view.View$1.onClick(View.java:4096)
                                                                           at android.view.View.performClick(View.java:4856)
                                                                           at android.view.View$PerformClick.run(View.java:19956)
                                                                           at android.os.Handler.handleCallback(Handler.java:739)
                                                                           at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                           at android.os.Looper.loop(Looper.java:211)
                                                                           at android.app.ActivityThread.main(ActivityThread.java:5371)
                                                                           at java.lang.reflect.Method.invoke(Native Method)
                                                                           at java.lang.reflect.Method.invoke(Method.java:372)
                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:945)
                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:740)
                                                                        Caused by: java.lang.reflect.InvocationTargetException
                                                                           at java.lang.reflect.Method.invoke(Native Method)
                                                                           at java.lang.reflect.Method.invoke(Method.java:372)
                                                                           at android.view.View$1.onClick(View.java:4091)
                                                                           at android.view.View.performClick(View.java:4856) 
                                                                           at android.view.View$PerformClick.run(View.java:19956) 
                                                                           at android.os.Handler.handleCallback(Handler.java:739) 
                                                                           at android.os.Handler.dispatchMessage(Handler.java:95) 
                                                                           at android.os.Looper.loop(Looper.java:211) 
                                                                           at android.app.ActivityThread.main(ActivityThread.java:5371) 
                                                                           at java.lang.reflect.Method.invoke(Native Method) 
                                                                           at java.lang.reflect.Method.invoke(Method.java:372) 
                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:945) 
                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:740) 
                                                                        Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void mycompany.mediaplayer.MusicService.setSong(int)' on a null object reference
                                                                           at mycompany.mediaplayer.MainActivity.songPicked(MainActivity.java:130)
                                                                           at java.lang.reflect.Method.invoke(Native Method) 
                                                                           at java.lang.reflect.Method.invoke(Method.java:372) 
                                                                           at android.view.View$1.onClick(View.java:4091) 
                                                                           at android.view.View.performClick(View.java:4856) 
                                                                           at android.view.View$PerformClick.run(View.java:19956) 
                                                                           at android.os.Handler.handleCallback(Handler.java:739) 
                                                                           at android.os.Handler.dispatchMessage(Handler.java:95) 
                                                                           at android.os.Looper.loop(Looper.java:211) 
                                                                           at android.app.ActivityThread.main(ActivityThread.java:5371) 
                                                                           at java.lang.reflect.Method.invoke(Native Method) 
                                                                           at java.lang.reflect.Method.invoke(Method.java:372) 
                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:945) 
                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:740) 
03-17 21:55:48.109 29835-29835/mycompany.mediaplayer I/Process: Sending signal. PID: 29835 SIG: 9

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

修正了它!

需要一段时间才能追踪,但我的错误是将调用“服务”放在Android清单中的“应用程序”部分之外。向上移动服务线可以解决问题。