我(合法地)将一些名为beatkeeper的应用程序中的项目代码复制并粘贴到我自己的应用程序中。我想实现一个节拍器。 应用程序beatkeeper本身工作正常,但是当我复制代码并运行我自己的应用程序时,它会在我点击开始/停止按钮时停止工作...
04-07 09:25:05.126: E/AndroidRuntime(2708): FATAL EXCEPTION: main
04-07 09:25:05.126: E/AndroidRuntime(2708): Process: nl.ruudjanssenmusicservices.desaxofoonapp, PID: 2708
04-07 09:25:05.126: E/AndroidRuntime(2708): java.lang.NullPointerException
04-07 09:25:05.126: E/AndroidRuntime(2708): at nl.ruudjanssenmusicservices.desaxofoonapp.MetronomeActivity$6.handleMessage(MetronomeActivity.java:54)
04-07 09:25:05.126: E/AndroidRuntime(2708): at android.os.Handler.dispatchMessage(Handler.java:102)
04-07 09:25:05.126: E/AndroidRuntime(2708): at android.os.Looper.loop(Looper.java:136)
04-07 09:25:05.126: E/AndroidRuntime(2708): at android.app.ActivityThread.main(ActivityThread.java:5017)
04-07 09:25:05.126: E/AndroidRuntime(2708): at java.lang.reflect.Method.invokeNative(Native Method)
04-07 09:25:05.126: E/AndroidRuntime(2708): at java.lang.reflect.Method.invoke(Method.java:515)
04-07 09:25:05.126: E/AndroidRuntime(2708): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
04-07 09:25:05.126: E/AndroidRuntime(2708): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
04-07 09:25:05.126: E/AndroidRuntime(2708): at dalvik.system.NativeStart.main(Native Method)
来源主要活动:
package nl.ruudjanssenmusicservices.desaxofoonapp;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.media.AudioManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Spinner;
import android.widget.TextView;
public class MetronomeActivity extends Activity {
private final short minBpm = 40;
private final short maxBpm = 208;
private short bpm = 100;
private short noteValue = 4;
private short beats = 4;
private short volume;
private short initialVolume;
private double beatSound = 2440;
private double sound = 6440;
private AudioManager audio;
private MetronomeAsyncTask metroTask;
private Button plusButton;
private Button minusButton;
private TextView currentBeat;
private Handler mHandler;
// have in mind that: http://stackoverflow.com/questions/11407943/this-handler-class-should-be-static-or-leaks-might-occur-incominghandler
// in this case we should be fine as no delayed messages are queued
private Handler getHandler() {
return new Handler() {
@Override
public void handleMessage(Message msg) {
String message = (String)msg.obj;
if(message.equals("1"))
currentBeat.setTextColor(Color.GREEN);
else
currentBeat.setTextColor(getResources().getColor(R.color.yellow));
currentBeat.setText(message);
}
};
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
metroTask = new MetronomeAsyncTask();
/* Set values and listeners to buttons and stuff */
TextView bpmText = (TextView) findViewById(R.id.bps);
bpmText.setText(""+bpm);
TextView timeSignatureText = (TextView) findViewById(R.id.timesignature);
timeSignatureText.setText(""+beats+"/"+noteValue);
plusButton = (Button) findViewById(R.id.plus);
plusButton.setOnLongClickListener(plusListener);
minusButton = (Button) findViewById(R.id.minus);
minusButton.setOnLongClickListener(minusListener);
// currentBeat = (TextView) findViewById(R.id.currentBeat);
//currentBeat.setTextColor(Color.GREEN);
Spinner beatSpinner = (Spinner) findViewById(R.id.beatspinner);
ArrayAdapter<Beats> arrayBeats =
new ArrayAdapter<Beats>(this,
android.R.layout.simple_spinner_item, Beats.values());
beatSpinner.setAdapter(arrayBeats);
beatSpinner.setSelection(Beats.four.ordinal());
arrayBeats.setDropDownViewResource(R.layout.spinner_dropdown);
beatSpinner.setOnItemSelectedListener(beatsSpinnerListener);
Spinner noteValuesdSpinner = (Spinner) findViewById(R.id.notespinner);
ArrayAdapter<NoteValues> noteValues =
new ArrayAdapter<NoteValues>(this,
android.R.layout.simple_spinner_item, NoteValues.values());
noteValuesdSpinner.setAdapter(noteValues);
noteValues.setDropDownViewResource(R.layout.spinner_dropdown);
noteValuesdSpinner.setOnItemSelectedListener(noteValueSpinnerListener);
audio = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
initialVolume = (short) audio.getStreamVolume(AudioManager.STREAM_MUSIC);
volume = initialVolume;
SeekBar volumebar = (SeekBar) findViewById(R.id.volumebar);
volumebar.setMax(audio.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
volumebar.setProgress(volume);
volumebar.setOnSeekBarChangeListener(volumeListener);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public synchronized void onStartStopClick(View view) {
Button button = (Button) view;
String buttonText = button.getText().toString();
if(buttonText.equalsIgnoreCase("start")) {
button.setText(R.string.stop);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
metroTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null);
else
metroTask.execute();
} else {
button.setText(R.string.start);
metroTask.stop();
metroTask = new MetronomeAsyncTask();
Runtime.getRuntime().gc();
}
}
private void maxBpmGuard() {
if(bpm >= maxBpm) {
plusButton.setEnabled(false);
plusButton.setPressed(false);
} else if(!minusButton.isEnabled() && bpm>minBpm) {
minusButton.setEnabled(true);
}
}
public void onPlusClick(View view) {
bpm++;
TextView bpmText = (TextView) findViewById(R.id.bps);
bpmText.setText(""+bpm);
metroTask.setBpm(bpm);
maxBpmGuard();
}
private OnLongClickListener plusListener = new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
// TODO Auto-generated method stub
bpm+=20;
if(bpm >= maxBpm)
bpm = maxBpm;
TextView bpmText = (TextView) findViewById(R.id.bps);
bpmText.setText(""+bpm);
metroTask.setBpm(bpm);
maxBpmGuard();
return true;
}
};
private void minBpmGuard() {
if(bpm <= minBpm) {
minusButton.setEnabled(false);
minusButton.setPressed(false);
} else if(!plusButton.isEnabled() && bpm<maxBpm) {
plusButton.setEnabled(true);
}
}
public void onMinusClick(View view) {
bpm--;
TextView bpmText = (TextView) findViewById(R.id.bps);
bpmText.setText(""+bpm);
metroTask.setBpm(bpm);
minBpmGuard();
}
private OnLongClickListener minusListener = new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
// TODO Auto-generated method stub
bpm-=20;
if(bpm <= minBpm)
bpm = minBpm;
TextView bpmText = (TextView) findViewById(R.id.bps);
bpmText.setText(""+bpm);
metroTask.setBpm(bpm);
minBpmGuard();
return true;
}
};
private OnSeekBarChangeListener volumeListener = new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
volume = (short) progress;
audio.setStreamVolume(AudioManager.STREAM_MUSIC, progress, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
};
private OnItemSelectedListener beatsSpinnerListener = new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
Beats beat = (Beats) arg0.getItemAtPosition(arg2);
TextView timeSignature = (TextView) findViewById(R.id.timesignature);
timeSignature.setText(""+beat+"/"+noteValue);
metroTask.setBeat(beat.getNum());
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
};
private OnItemSelectedListener noteValueSpinnerListener = new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
NoteValues noteValue = (NoteValues) arg0.getItemAtPosition(arg2);
TextView timeSignature = (TextView) findViewById(R.id.timesignature);
timeSignature.setText(""+beats+"/"+noteValue);
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
};
@Override
public boolean onKeyUp(int keycode, KeyEvent e) {
SeekBar volumebar = (SeekBar) findViewById(R.id.volumebar);
volume = (short) audio.getStreamVolume(AudioManager.STREAM_MUSIC);
switch(keycode) {
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
volumebar.setProgress(volume);
break;
}
return super.onKeyUp(keycode, e);
}
public void onBackPressed() {
metroTask.stop();
// metroTask = new MetronomeAsyncTask();
Runtime.getRuntime().gc();
audio.setStreamVolume(AudioManager.STREAM_MUSIC, initialVolume, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
finish();
}
private class MetronomeAsyncTask extends AsyncTask<Void,Void,String> {
Metronome metronome;
MetronomeAsyncTask() {
mHandler = getHandler();
metronome = new Metronome(mHandler);
}
protected String doInBackground(Void... params) {
metronome.setBeat(beats);
metronome.setNoteValue(noteValue);
metronome.setBpm(bpm);
metronome.setBeatSound(beatSound);
metronome.setSound(sound);
metronome.play();
return null;
}
public void stop() {
metronome.stop();
metronome = null;
}
public void setBpm(short bpm) {
metronome.setBpm(bpm);
metronome.calcSilence();
}
public void setBeat(short beat) {
if(metronome != null)
metronome.setBeat(beat);
}
}
}
我认为第48行的'private Handler getHandler'可能存在问题,但我完全不知道如何解决这个问题......
编辑:请求发布节拍器类:
package nl.ruudjanssenmusicservices.desaxofoonapp;
import android.os.Handler;
import android.os.Message;
public class Metronome {
private double bpm;
private int beat;
private int noteValue;
private int silence;
private double beatSound;
private double sound;
private final int tick = 1000; // samples of tick
private boolean play = true;
private AudioGenerator audioGenerator = new AudioGenerator(8000);
private Handler mHandler;
private double[] soundTickArray;
private double[] soundTockArray;
private double[] silenceSoundArray;
private Message msg;
private int currentBeat = 1;
public Metronome(Handler handler) {
audioGenerator.createPlayer();
this.mHandler = handler;
}
public void calcSilence() {
silence = (int) (((60/bpm)*8000)-tick);
soundTickArray = new double[this.tick];
soundTockArray = new double[this.tick];
silenceSoundArray = new double[this.silence];
msg = new Message();
msg.obj = ""+currentBeat;
double[] tick = audioGenerator.getSineWave(this.tick, 8000, beatSound);
double[] tock = audioGenerator.getSineWave(this.tick, 8000, sound);
for(int i=0;i<this.tick;i++) {
soundTickArray[i] = tick[i];
soundTockArray[i] = tock[i];
}
for(int i=0;i<silence;i++)
silenceSoundArray[i] = 0;
}
public void play() {
calcSilence();
do {
msg = new Message();
msg.obj = ""+currentBeat;
if(currentBeat == 1)
audioGenerator.writeSound(soundTockArray);
// else
// audioGenerator.writeSound(soundTickArray);
if(bpm <= 120)
mHandler.sendMessage(msg);
audioGenerator.writeSound(silenceSoundArray);
if(bpm > 120)
mHandler.sendMessage(msg);
currentBeat++;
if(currentBeat > beat)
currentBeat = 1;
} while(play);
}
public void stop() {
play = false;
audioGenerator.destroyAudioTrack();
}
public double getBpm() {
return bpm;
}
public void setBpm(int bpm) {
this.bpm = bpm;
}
public int getNoteValue() {
return noteValue;
}
public void setNoteValue(int bpmetre) {
this.noteValue = bpmetre;
}
public int getBeat() {
return beat;
}
public void setBeat(int beat) {
this.beat = beat;
}
public double getBeatSound() {
return beatSound;
}
public void setBeatSound(double sound1) {
this.beatSound = sound1;
}
public double getSound() {
return sound;
}
public void setSound(double sound2) {
this.sound = sound2;
}
}
答案 0 :(得分:0)
onHandleMessage();中的currentBeat为null;