我正在尝试实现一个音乐播放器应用程序(在tutsplus.com中给出)我得到以下异常:
06-19 12:28:06.457 14867-14867/com.example.adityakrishnakumar.mymusicplayer E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.adityakrishnakumar.mymusicplayer, PID: 14867
java.lang.IllegalStateException: Could not execute method of the activity
at android.view.View$1.onClick(View.java:3978)
at android.view.View.performClick(View.java:4646)
at android.view.View$PerformClick.run(View.java:19403)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5511)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at android.view.View$1.onClick(View.java:3973)
at android.view.View.performClick(View.java:4646)
at android.view.View$PerformClick.run(View.java:19403)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5511)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.example.adityakrishnakumar.mymusicplayer.MainActivity.songPicked(MainActivity.java:98)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at android.view.View$1.onClick(View.java:3973)
at android.view.View.performClick(View.java:4646)
at android.view.View$PerformClick.run(View.java:19403)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5511)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
at dalvik.system.NativeStart.main(Native Method)
MainActivity的代码如下:
package com.example.adityakrishnakumar.mymusicplayer;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.MediaStore;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
import android.widget.MediaController;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class MainActivity extends AppCompatActivity implements MediaController.MediaPlayerControl{
private ArrayList<Song> songList;
private ListView songView;
private MusicService musicService;
private Intent playIntent;
private boolean musicBound = false;
private MusicController controller;
private boolean paused = false, playbackPaused = false;
@Override
protected void onPause(){
super.onPause();
paused = true;
}
@Override
protected void onResume(){
super.onResume();
if(paused){
setController();
paused = false;
}
}
@Override
protected void onStop(){
controller.hide();
super.onStop();
}
private void setController(){
controller = new MusicController(this);
controller.setPrevNextListeners(new View.OnClickListener() {
@Override
public void onClick(View v) {
playNext();
}
}, new View.OnClickListener() {
@Override
public void onClick(View v) {
playPrev();
}
});
controller.setMediaPlayer(this);
controller.setAnchorView(findViewById(R.id.song_list));
controller.setEnabled(true);
}
private void playPrev() {
musicService.playPrev();
if(playbackPaused){
setController();
playbackPaused = false;
}
controller.show(0);
}
private void playNext() {
musicService.playNext();
if(playbackPaused){
setController();
playbackPaused = false;
}
controller.show(0);
}
public void songPicked(View view)
{
int songIndex = Integer.parseInt(view.getTag().toString());
musicService.setSong(songIndex);
musicService.playSong();
if(playbackPaused){
setController();
playbackPaused = false;
}
controller.show(0);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
setController();
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
songView = (ListView) findViewById(R.id.song_list);
songList = new ArrayList<Song>();
getSongList();
//Displaying the songs
Collections.sort(songList, new Comparator<Song>() {
@Override
public int compare(Song lhs, Song rhs) {
return lhs.getTitle().compareTo(rhs.getTitle());
}
});
SongAdapter songAdapter = new SongAdapter(this,songList);
songView.setAdapter(songAdapter);
}
private ServiceConnection musicConnection = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.MusicBinder binder = (MusicService.MusicBinder) service;
// get service
musicService = binder.getService();
//pass the list
musicService.setList(songList);
musicBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
musicBound = false;
}
};
@Override
protected void onStart(){
super.onStart();
if(playIntent == null)
{
playIntent = new Intent(this, MusicService.class);
bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
startService(playIntent);
}
}
@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.
switch (item.getItemId())
{
case R.id.action_shuffle:
musicService.setShuffle();
break;
case R.id.action_end:
stopService(playIntent);
musicService = null;
System.exit(0);
break;
}
//noinspection SimplifiableIfStatement
return super.onOptionsItemSelected(item);
}
public void getSongList()
{
// retrieve song info
ContentResolver musicResolver = getContentResolver();
Uri musicUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor musicCursor = musicResolver.query(musicUri,null,null,null,null);
int idColumn = 0;
int titleColumn = 0;
int artistColumn = 0;
// Checking whether we have valid data
if(musicCursor != null && musicCursor.moveToFirst())
{
titleColumn = musicCursor.getColumnIndex(MediaStore.Audio.Media.TITLE);
idColumn = musicCursor.getColumnIndex(MediaStore.Audio.Media._ID);
artistColumn = musicCursor.getColumnIndex(MediaStore.Audio.Media.ARTIST);
}
// Adding 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));
} while(musicCursor.moveToNext());
}
@Override
protected void onDestroy()
{
stopService(playIntent);
musicService = null;
super.onDestroy();
}
@Override
public void start() {
musicService.go();
}
@Override
public void pause() {
playbackPaused = true;
musicService.pausePlayer();
}
@Override
public int getDuration() {
if(musicService != null && musicBound && musicService.isPng())
{
return musicService.getDur();
}
else
{
return 0;
}
}
@Override
public int getCurrentPosition() {
if(musicService != null && musicBound && musicService.isPng())
{
return musicService.getPosn();
}
else
{
return 0;
}
}
@Override
public void seekTo(int pos) {
musicService.seek(pos);
}
@Override
public boolean isPlaying() {
if(musicService != null && musicBound)
{
return musicService.isPng();
}
else
{
return false;
}
}
@Override
public int getBufferPercentage() {
return 0;
}
@Override
public boolean canPause() {
return true;
}
@Override
public boolean canSeekBackward() {
return true;
}
@Override
public boolean canSeekForward() {
return true;
}
@Override
public int getAudioSessionId() {
return 0;
}
public void onCompletion(MediaPlayer mp)
{
}
public boolean onError(MediaPlayer mp, int a, int b)
{
return false;
}
}
Custom MusicService Java类如下:
package com.example.adityakrishnakumar.mymusicplayer;
import android.app.Notification;
import android.app.PendingIntent;
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.provider.MediaStore;
import android.util.Log;
import java.util.ArrayList;
import java.util.Random;
public class MusicService extends Service implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener,MediaPlayer.OnCompletionListener{
private static final int NOTIFY_ID = 1;
private String songTitle = null;
private boolean shuffle = false;
private Random rand;
public MusicService() {
}
private MediaPlayer player;
private ArrayList<Song> songs;
private int songPosn;
private final IBinder musicBind = new MusicBinder();
public IBinder onIBind(Intent intent){
return musicBind;
}
public boolean onUnbind(Intent intent){
player.stop();
player.release();
return false;
}
public void playSong(){
player.reset();
Song playSong = songs.get(songPosn);
songTitle = playSong.getTitle();
long currSong = playSong.getId();
Uri trackUri = ContentUris.withAppendedId(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 IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return null;
}
@Override
public void onCompletion(MediaPlayer mp) {
if(player.getCurrentPosition() > 0)
{
mp.reset();
playNext();
}
}
@Override
public void onCreate(){
// create service
super.onCreate();
//initialize position
rand = new Random();
songPosn = 0;
player = new MediaPlayer();
initMusicPlayer();
}
public void setShuffle(){
if(shuffle) shuffle = false;
else
shuffle = true;
}
public void initMusicPlayer(){
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 boolean onError(MediaPlayer mp, int what, int extra) {
mp.reset();
return false;
}
@Override
public void onPrepared(MediaPlayer mp)
{
mp.start();
Intent notIntent = new Intent(this, MainActivity.class);
notIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,notIntent,PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder builder = new Notification.Builder(this);
builder.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.play)
.setTicker(songTitle)
.setOngoing(true)
.setContentTitle("Playing")
.setContentText(songTitle);
Notification not = builder.build();
startForeground(NOTIFY_ID,not);
}
public void setSong(int songIndex)
{
songPosn = songIndex;
}
public int getPosn()
{
return player.getCurrentPosition();
}
public int getDur()
{
return player.getDuration();
}
public boolean isPng()
{
return player.isPlaying();
}
public void pausePlayer(){
player.pause();
}
public void seek(int posn)
{
player.seekTo(posn);
}
public void go()
{
player.start();
}
public void playPrev()
{
songPosn--;
if(songPosn < 0 )
{
songPosn = songs.size()-1;
}
playSong();
}
public void playNext(){
if(shuffle)
{
int newSong = songPosn;
while(newSong == songPosn)
{
newSong = rand.nextInt(songs.size());
}
songPosn = newSong;
}
else
{
songPosn++;
if(songPosn >= songs.size()) songPosn = 0;
}
playSong();
}
@Override
public void onDestroy()
{
stopForeground(true);
}
}
SongAdapter(存储音乐信息如下:
package com.example.adityakrishnakumar.mymusicplayer;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
public class SongAdapter extends BaseAdapter {
private ArrayList<Song> songs;
private LayoutInflater songInf;
public SongAdapter(Context c, ArrayList<Song> theSongs)
{
songs = theSongs;
songInf = LayoutInflater.from(c);
}
@Override
public int getCount() {
return songs.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// map to song layout
LinearLayout songLay = (LinearLayout)songInf.inflate(R.layout.song,parent,false);
//Get Title and artist views
TextView songView = (TextView) songLay.findViewById(R.id.song_title);
TextView artistView = (TextView) songLay.findViewById(R.id.song_artist);
// get the song using position
Song currSong = songs.get(position);
// Get Title & Artist Strings
songView.setText(currSong.getTitle());
artistView.setText(currSong.getArtist());
// Set Position as tag
songLay.setTag(position);
return songLay;
}
}
音乐播放控制器(MusicController)如下:
package com.example.adityakrishnakumar.mymusicplayer;
import android.annotation.TargetApi;
import android.content.Context;
import android.widget.MediaController;
import android.os.Build;
public class MusicController extends MediaController {
public MusicController(Context c)
{
super(c);
}
public void hide(){}
}
我还在Manifest中提供了以下权限:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
The XML that gives the song name and artist name is as follows (song.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:onClick="songPicked"
android:orientation="vertical"
android:padding="5dp">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/song_title"
android:textColor="#ffffff99"
android:textSize="20sp"
android:textStyle="bold"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/song_artist"
android:textColor="#ffffff99"
android:textSize="15sp"
/>
</LinearLayout>
提前致谢...
答案 0 :(得分:1)
你在这一行得到NullPointerExeception
。
int songIndex = Integer.parseInt(view.getTag().toString());
首先检查view.getTag().toString()
是否为空。
这样写
public void songPicked(View view)
{
if(view.getTag().toString() != null){
int songIndex = Integer.parseInt(view.getTag().toString());
}
musicService.setSong(songIndex);
musicService.playSong();
if(playbackPaused){
setController();
playbackPaused = false;
}
controller.show(0);
}