1

私は次のBaseClassを持っています:

public class BaseClass extends Activity implements MusicUtils.Defs,
    View.OnTouchListener, View.OnLongClickListener {
private static final int USE_AS_RINGTONE = CHILD_MENU_BASE;

private boolean mOneShot = false;
private boolean mSeeking = false;
private boolean mDeviceHasDpad;
private long mStartSeekenter code herePos = 0;
private long mLastSeekEventTime;
private IMediaPlaybackService mService = null;
private RepeatingImageButton mPrevButton;
private ImageButton mPauseButton;
private RepeatingImageButton mNextButton;
private Worker mAlbumArtWorker;
private AlbumArtHandler mAlbumArtHandler;
private Toast mToast;
private int mTouchSlop;
private ServiceToken mToken;

public BaseClass() {
}

@Override
public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setVolumeControlStream(AudioManager.STREAM_MUSIC);

    mAlbumArtWorker = new Worker("album art worker");
    mAlbumArtHandler = new AlbumArtHandler(mAlbumArtWorker.getLooper());

    mCurrentTime = (TextView) findViewById(R.id.currenttime);
    mTotalTime = (TextView) findViewById(R.id.totaltime);

    mPrevButton = (RepeatingImageButton) findViewById(R.id.prev);
    mPrevButton.setOnClickListener(mPrevListener);
    mPrevButton.setRepeatListener(mRewListener, 260);
    mPauseButton = (ImageButton) findViewById(R.id.pause);
    mPauseButton.requestFocus();
    mPauseButton.setOnClickListener(mPauseListener);
    mNextButton = (RepeatingImageButton) findViewById(R.id.next);
    mNextButton.setOnClickListener(mNextListener);
    mNextButton.setRepeatListener(mFfwdListener, 260);
    seekmethod = 1;

    mDeviceHasDpad = (getResources().getConfiguration().navigation ==

    Configuration.NAVIGATION_DPAD);

    if (icicle != null) {
        mOneShot = icicle.getBoolean("oneshot");
    } else {
        mOneShot = getIntent().getBooleanExtra("oneshot", false);
    }

    mTouchSlop = ViewConfiguration.get(BaseClass.this).getScaledTouchSlop();
  }



  Handler mLabelScroller = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        TextView tv = (TextView) msg.obj;
        int x = tv.getScrollX();
        x = x * 3 / 4;
        tv.scrollTo(x, 0);
        if (x == 0) {
            tv.setEllipsize(TruncateAt.END);
        } else {
            Message newmsg = obtainMessage(0, tv);
            mLabelScroller.sendMessageDelayed(newmsg, 15);
        }
    }
   };


    Cursor c = MusicUtils.query(this, ContentUris.withAppendedId(
            MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, audioid),
            new String[] { MediaStore.Audio.Media.IS_MUSIC }, null, 

     null,
            null);
    boolean ismusic = true;
    if (c != null) {
        if (c.moveToFirst()) {
            ismusic = c.getInt(0) != 0;
        }
        c.close();
    }
    if (!ismusic) {
        return false;
    }

    boolean knownartist = (artist != null)
            && !MediaStore.UNKNOWN_STRING.equals(artist);

    boolean knownalbum = (album != null)
            && !MediaStore.UNKNOWN_STRING.equals(album);

    title = getString(R.string.mediasearch, title);

    Intent i = new Intent();
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    i.setAction(MediaStore.INTENT_ACTION_MEDIA_SEARCH);
    i.putExtra(SearchManager.QUERY, query);
    if (knownartist) {
        i.putExtra(MediaStore.EXTRA_MEDIA_ARTIST, artist);
    }
    if (knownalbum) {
        i.putExtra(MediaStore.EXTRA_MEDIA_ALBUM, album);
    }
    i.putExtra(MediaStore.EXTRA_MEDIA_TITLE, song);
    i.putExtra(MediaStore.EXTRA_MEDIA_FOCUS, mime);

    startActivity(Intent.createChooser(i, title));
    return true;
}

private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
    public void onStartTrackingTouch(SeekBar bar) {
        mLastSeekEventTime = 0;
        mFromTouch = true;
    }

    public void onProgressChanged(SeekBar bar, int progress,
            boolean fromuser) {
        if (!fromuser || (mService == null))
            return;
        long now = SystemClock.elapsedRealtime();
        if ((now - mLastSeekEventTime) > 250) {
            mLastSeekEventTime = now;
            updateTrackInfo();
            mPosOverride = mDuration * progress / 1000;
            try {
                mService.seek(mPosOverride);
            } catch (RemoteException ex) {
            }

            // trackball event, allow progress updates
            if (!mFromTouch) {
                refreshNow();
                mPosOverride = -1;
            }
        }
    }



private View.OnClickListener mPauseListener = new View.OnClickListener() {
    public void onClick(View v) {
        doPauseResume();
    }
};

private View.OnClickListener mPrevListener = new View.OnClickListener() {
    public void onClick(View v) {
        if (mService == null)
            return;
        try {
            if (mService.position() < 2000) {
                mService.prev();
            } else {
                mService.seek(0);
                mService.play();
            }
        } catch (RemoteException ex) {
        }
    }
};

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    try {
        switch (keyCode) {
        case KeyEvent.KEYCODE_DPAD_LEFT:
            if (!useDpadMusicControl()) {
                break;
            }
            if (mService != null) {
                if (!mSeeking && mStartSeekPos >= 0) {
                    mPauseButton.requestFocus();
                    if (mStartSeekPos < 1000) {
                        mService.prev();
                    } else {
                        mService.seek(0);
                    }
                } else {
                    scanBackward(-1,
                            event.getEventTime() - 

      event.getDownTime());
                    mPauseButton.requestFocus();
                    mStartSeekPos = -1;
                }
            }
            mSeeking = false;
            mPosOverride = -1;
            return true;
        case KeyEvent.KEYCODE_DPAD_RIGHT:
            if (!useDpadMusicControl()) {
                break;
            }
            if (mService != null) {
                if (!mSeeking && mStartSeekPos >= 0) {
                    mPauseButton.requestFocus();
                    mService.next();
                } else {
                    scanForward(-1,
                            event.getEventTime() - 

     event.getDownTime());
                    mPauseButton.requestFocus();
                    mStartSeekPos = -1;
                }
            }
            mSeeking = false;
            mPosOverride = -1;
            return true;
        }
    } catch (RemoteException ex) {
    }
    return super.onKeyUp(keyCode, event);
}

private boolean useDpadMusicControl() {
    if (mDeviceHasDpad
            && (mPrevButton.isFocused() || mNextButton.isFocused() 

      || mPauseButton
                    .isFocused())) {
        return true;
    }
    return false;
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    int repcnt = event.getRepeatCount();

    if ((seekmethod == 0) ? seekMethod1(keyCode) : seekMethod2(keyCode))
        return true;

    switch (keyCode) {
    /*
     * // image scale case KeyEvent.KEYCODE_Q: av.adjustParams(-0.05, 0.0,
     * 0.0, 0.0, 0.0,-1.0); break; case KeyEvent.KEYCODE_E: av.adjustParams(
     * 0.05, 0.0, 0.0, 0.0, 0.0, 1.0); break; // image translate case
     * KeyEvent.KEYCODE_W: av.adjustParams( 0.0, 0.0,-1.0, 0.0, 0.0, 0.0);
     * break; case KeyEvent.KEYCODE_X: av.adjustParams( 0.0, 0.0, 1.0, 0.0,
     * 0.0, 0.0); break; case KeyEvent.KEYCODE_A: av.adjustParams( 0.0,-1.0,
     * 0.0, 0.0, 0.0, 0.0); break; case KeyEvent.KEYCODE_D: av.adjustParams(
     * 0.0, 1.0, 0.0, 0.0, 0.0, 0.0); break; // camera rotation case
     * KeyEvent.KEYCODE_R: av.adjustParams( 0.0, 0.0, 0.0, 0.0, 0.0,-1.0);
     * break; case KeyEvent.KEYCODE_U: av.adjustParams( 0.0, 0.0, 0.0, 0.0,
     * 0.0, 1.0); break; // camera translate case KeyEvent.KEYCODE_Y:
     * av.adjustParams( 0.0, 0.0, 0.0, 0.0,-1.0, 0.0); break; case
     * KeyEvent.KEYCODE_N: av.adjustParams( 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
     * break; case KeyEvent.KEYCODE_G: av.adjustParams( 0.0, 0.0, 0.0,-1.0,
     * 0.0, 0.0); break; case KeyEvent.KEYCODE_J: av.adjustParams( 0.0, 0.0,
     * 0.0, 1.0, 0.0, 0.0); break;
     */

    case KeyEvent.KEYCODE_SLASH:
        seekmethod = 1 - seekmethod;
        return true;

    case KeyEvent.KEYCODE_DPAD_LEFT:
        if (!useDpadMusicControl()) {
            break;
        }
        if (!mPrevButton.hasFocus()) {
            mPrevButton.requestFocus();
        }
        scanBackward(repcnt, event.getEventTime() - 

      event.getDownTime());
        return true;
    case KeyEvent.KEYCODE_DPAD_RIGHT:
        if (!useDpadMusicControl()) {
            break;
        }
        if (!mNextButton.hasFocus()) {
            mNextButton.requestFocus();
        }
        scanForward(repcnt, event.getEventTime() - event.getDownTime());
        return true;

    case KeyEvent.KEYCODE_S:
        toggleShuffle();
        return true;

    case KeyEvent.KEYCODE_DPAD_CENTER:
    case KeyEvent.KEYCODE_SPACE:
        doPauseResume();
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

private void scanBackward(int repcnt, long delta) {
    if (mService == null)
        return;
    try {
        if (repcnt == 0) {
            mStartSeekPos = mService.position();
            mLastSeekEventTime = 0;
            mSeeking = false;
        } else {
            mSeeking = true;
            if (delta < 5000) {
                // seek at 10x speed for the first 5 seconds
                delta = delta * 10;
            } else {
                // seek at 40x after that
                delta = 50000 + (delta - 5000) * 40;
            }
            long newpos = mStartSeekPos - delta;
            if (newpos < 0) {
                // move to previous track
                mService.prev();
                long duration = mService.duration();
                mStartSeekPos += duration;
                newpos += duration;
            }
            if (((delta - mLastSeekEventTime) > 250) || repcnt < 0) 

            {
                mService.seek(newpos);
                mLastSeekEventTime = delta;
            }
            if (repcnt >= 0) {
                mPosOverride = newpos;
            } else {
                mPosOverride = -1;
            }
            refreshNow();
        }
    } catch (RemoteException ex) {
    }
}

private void scanForward(int repcnt, long delta) {
    if (mService == null)
        return;
    try {
        if (repcnt == 0) {
            mStartSeekPos = mService.position();
            mLastSeekEventTime = 0;
            mSeeking = false;
        } else {
            mSeeking = true;
            if (delta < 5000) {
                // seek at 10x speed for the first 5 seconds
                delta = delta * 10;
            } else {
                // seek at 40x after that
                delta = 50000 + (delta - 5000) * 40;
            }
            long newpos = mStartSeekPos + delta;
            long duration = mService.duration();
            if (newpos >= duration) {
                // move to next track
                mService.next();
                mStartSeekPos -= duration; // is OK to go 


          negative
                newpos -= duration;
            }
            if (((delta - mLastSeekEventTime) > 250) || repcnt < 0) {
                mService.seek(newpos);
                mLastSeekEventTime = delta;
            }
            if (repcnt >= 0) {
                mPosOverride = newpos;
            } else {
                mPosOverride = -1;
            }
            refreshNow();
        }
    } catch (RemoteException ex) {
    }
}

private void doPauseResume() {
    try {
        if (mService != null) {
            if (mService.isPlaying()) {
                mService.pause();
            } else {
                mService.play();
            }
            updateTrackInfo();
            refreshNow();
            setPauseButtonImage();
        }
    } catch (RemoteException ex) {
    }
}

private void toggleShuffle() {
    if (mService == null) {
        return;
    }
    try {
        int shuffle = mService.getShuffleMode();
        if (shuffle == MediaPlaybackService.SHUFFLE_NONE) {


    mService.setShuffleMode(MediaPlaybackService.SHUFFLE_NORMAL);
            if (mService.getRepeatMode() ==            

    MediaPlaybackService.REPEAT_CURRENT) {
                mService.setRepeatMode(MediaPlaybackService.REPEAT_ALL);
            }
            showToast(R.string.shuffle_on_notif);
        } else if (shuffle == MediaPlaybackService.SHUFFLE_NORMAL
                || shuffle == MediaPlaybackService.SHUFFLE_AUTO) {
            mService.setShuffleMode(MediaPlaybackService.SHUFFLE_NONE);
            showToast(R.string.shuffle_off_notif);
        } else {
            Log.e("MediaPlaybackActivity", "Invalid shuffle mode: "
                    + shuffle);
        }
    } catch (RemoteException ex) {
    }
}

private void cycleRepeat() {
    if (mService == null) {
        return;
    }
    try {
        int mode = mService.getRepeatMode();
        if (mode == MediaPlaybackService.REPEAT_NONE) {
            mService.setRepeatMode(MediaPlaybackService.REPEAT_ALL);
            showToast(R.string.repeat_all_notif);
        } else if (mode == MediaPlaybackService.REPEAT_ALL) {
            mService.setRepeatMode(MediaPlaybackService.REPEAT_CURRENT);
            if (mService.getShuffleMode() != MediaPlaybackService.SHUFFLE_NONE) {
                mService.setShuffleMode(MediaPlaybackService.SHUFFLE_NONE);
            }
            showToast(R.string.repeat_current_notif);
        } else {
            mService.setRepeatMode(MediaPlaybackService.REPEAT_NONE);
            showToast(R.string.repeat_off_notif);
        }
    } catch (RemoteException ex) {
    }

}

private void showToast(int resid) {
    if (mToast == null) {
        mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
    }
    mToast.setText(resid);
    mToast.show();
}

private void startPlayback() {

    if (mService == null)
        return;
    Intent intent = getIntent();
    String filename = "";
    Uri uri = intent.getData();
    if (uri != null && uri.toString().length() > 0) {
        // If this is a file:// URI, just use the path directly instead
        // of going through the open-from-filedescriptor codepath.
        String scheme = uri.getScheme();
        if ("file".equals(scheme)) {
            filename = uri.getPath();
        } else {
            filename = uri.toString();
        }
        try {
            if (!ContentResolver.SCHEME_CONTENT.equals(scheme)
                    || !MediaStore.AUTHORITY.equals(uri.getAuthority())) {
                mOneShot = true;
            }
            mService.stop();
            mService.openFile(filename, mOneShot);
            mService.play();
            setIntent(new Intent());
        } catch (Exception ex) {
            Log.d("MediaPlaybackActivity", "couldn't start playback: " + ex);
        }
    }

    updateTrackInfo();
    long next = refreshNow();
    queueNextRefresh(next);
}

private ServiceConnection osc = new ServiceConnection() {
    public void onServiceConnected(ComponentName classname, IBinder obj) {
        mService = IMediaPlaybackService.Stub.asInterface(obj);
        startPlayback();
        try {
            // Assume something is playing when the service says it is,
            // but also if the audio ID is valid but the service is paused.
            if (mService.getAudioId() >= 0 || mService.isPlaying()
                    || mService.getPath() != null) {
                // something is playing now, we're done
                setPauseButtonImage();
                return;
            }
        } catch (RemoteException ex) {
        }
        // Service is dead or not playing anything. If we got here as part
        // of a "play this file" Intent, exit. Otherwise go to the Music
        // app start screen.
        if (getIntent().getData() == null) {
            Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setClass(BaseClass.this, MusicBrowserActivity.class);
            startActivity(intent);
        }
        finish();
    }

    public void onServiceDisconnected(ComponentName classname) {
        mService = null;
    }
};

private void setPauseButtonImage() {
    try {
        if (mService != null && mService.isPlaying()) {
            mPauseButton
                    .setImageResource(android.R.drawable.ic_media_pause);
        } else {
            mPauseButton.setImageResource(android.R.drawable.ic_media_play);
        }
    } catch (RemoteException ex) {
    }
}

private TextView mCurrentTime;
private TextView mTotalTime;

private long mPosOverride = -1;
private boolean mFromTouch = false;
private long mDuration;
private int seekmethod;
private boolean paused;

private static final int REFRESH = 1;
private static final int QUIT = 2;
private static final int GET_ALBUM_ART = 3;
private static final int ALBUM_ART_DECODED = 4;

private void queueNextRefresh(long delay) {
    if (!paused) {
        Message msg = mHandler.obtainMessage(REFRESH);
        mHandler.removeMessages(REFRESH);
        mHandler.sendMessageDelayed(msg, delay);
    }
}

private long refreshNow() {
    if (mService == null)
        return 500;
    try {
        long pos = mPosOverride < 0 ? mService.position() : mPosOverride;
        long remaining = 1000 - (pos % 1000);
        if ((pos >= 0) && (mService.duration() > 0)) {
            mCurrentTime.setText(MusicUtils
                    .makeTimeString(this, pos / 1000));

            if (mService.isPlaying()) {
                mCurrentTime.setVisibility(View.VISIBLE);
            } else {
                // blink the counter
                int vis = mCurrentTime.getVisibility();
                mCurrentTime
                        .setVisibility(vis == View.INVISIBLE ? View.VISIBLE
                                : View.INVISIBLE);
                remaining = 500;
            }

        } else {
            mCurrentTime.setText("--:--");

        }
        // return the number of milliseconds until the next full second, so
        // the counter can be updated at just the right time
        return remaining;
    } catch (RemoteException ex) {
    }
    return 500;
}

private final Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {

        case REFRESH:
            updateTrackInfo();
            long next = refreshNow();
            queueNextRefresh(next);
            break;

        case QUIT:
            // This can be moved back to onCreate once the bug that prevents
            // Dialogs from being started from onCreate/onResume is fixed.
            new AlertDialog.Builder(BaseClass.this)
                    .setTitle(R.string.service_start_error_title)
                    .setMessage(R.string.service_start_error_msg)
                    .setPositiveButton(R.string.service_start_error_button,
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog,
                                        int whichButton) {
                                    finish();
                                }
                            }).setCancelable(false).show();
            break;

        default:
            break;
        }
    }
};

private BroadcastReceiver mStatusListener = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action.equals(MediaPlaybackService.META_CHANGED)) {
            // redraw the artist/title info and
            // set new max for progress bar
            updateTrackInfo();
            setPauseButtonImage();
            queueNextRefresh(1);
        } else if (action.equals(MediaPlaybackService.PLAYBACK_COMPLETE)) {
            if (mOneShot) {
                finish();
            } else {
                setPauseButtonImage();
            }
        } else if (action.equals(MediaPlaybackService.PLAYSTATE_CHANGED)) {
            setPauseButtonImage();
        }
    }
};

private static class AlbumSongIdWrapper {
    public long albumid;
    public long songid;

    AlbumSongIdWrapper(long aid, long sid) {
        albumid = aid;
        songid = sid;
    }
}

private void updateTrackInfo() {
    if (mService == null) {
        return;
    }
    try {
        String path = mService.getPath();
        if (path == null) {
            finish();
            return;
        }

        long songid = mService.getAudioId();
        if (songid < 0 && path.toLowerCase().startsWith("http://")) {
            // Once we can get album art and meta data from MediaPlayer, we
            // can show that info again when streaming.
            mAlbumArtHandler.removeMessages(GET_ALBUM_ART);
            mAlbumArtHandler.obtainMessage(GET_ALBUM_ART,
                    new AlbumSongIdWrapper(-1, -1)).sendToTarget();
        } else {
            String artistName = mService.getArtistName();
            if (MediaStore.UNKNOWN_STRING.equals(artistName)) {
                artistName = getString(R.string.unknown_artist_name);
            }
            String albumName = mService.getAlbumName();
            long albumid = mService.getAlbumId();
            if (MediaStore.UNKNOWN_STRING.equals(albumName)) {
                albumName = getString(R.string.unknown_album_name);
                albumid = -1;
            }
            mAlbumArtHandler.removeMessages(GET_ALBUM_ART);
            mAlbumArtHandler.obtainMessage(GET_ALBUM_ART,
                    new AlbumSongIdWrapper(albumid, songid)).sendToTarget();
        }
        mDuration = mService.duration();
        mTotalTime.setText(MusicUtils
                .makeTimeString(this, mDuration / 1000));
    } catch (RemoteException ex) {
        finish();
    }
}

public class AlbumArtHandler extends Handler {
    private long mAlbumId = -1;

    public AlbumArtHandler(Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg) {
        long albumid = ((AlbumSongIdWrapper) msg.obj).albumid;
        long songid = ((AlbumSongIdWrapper) msg.obj).songid;
        if (msg.what == GET_ALBUM_ART
                && (mAlbumId != albumid || albumid < 0)) {
            // while decoding the new image, show the default album art
            Message numsg = mHandler.obtainMessage(ALBUM_ART_DECODED, null);
            mHandler.removeMessages(ALBUM_ART_DECODED);
            mHandler.sendMessageDelayed(numsg, 300);
            Bitmap bm = MusicUtils.getArtwork(BaseClass.this, songid,
                    albumid);
            if (bm == null) {
                bm = MusicUtils.getArtwork(BaseClass.this, songid, -1);
                albumid = -1;
            }
            if (bm != null) {
                numsg = mHandler.obtainMessage(ALBUM_ART_DECODED, bm);
                mHandler.removeMessages(ALBUM_ART_DECODED);
                mHandler.sendMessage(numsg);
            }
            mAlbumId = albumid;
        }
    }
}

public static class Worker implements Runnable {
    private final Object mLock = new Object();
    private Looper mLooper;

    /**
     * Creates a worker thread with the given name. The thread then runs a
     * {@link android.os.Looper}.
     * 
     * @param name
     *            A name for the new thread
     */
    Worker(String name) {
        Thread t = new Thread(null, this, name);
        t.setPriority(Thread.MIN_PRIORITY);
        t.start();
        synchronized (mLock) {
            while (mLooper == null) {
                try {
                    mLock.wait();
                } catch (InterruptedException ex) {
                }
            }
        }
    }

    public Looper getLooper() {
        return mLooper;
    }

    public void run() {
        synchronized (mLock) {
            Looper.prepare();
            mLooper = Looper.myLooper();
            mLock.notifyAll();
        }
        Looper.loop();
    }

    public void quit() {
        mLooper.quit();
    }
}

}

そして、このクラスを拡張したいのですが、プログラムがクラッシュし、この基本クラスでnullポインター例外が表示されます。基本クラスにはコンテンツビューがなく、ボタン(前のボタンと次のボタン)を指し、次のように表示されます。 nullポインタ..この問題を解決するために私を案内してください。

4

1 に答える 1

1

子クラスにcontentviewを設定すると、親クラスがそれにアクセスできます。

于 2012-11-01T11:25:43.153 に答える