Creare un xml activity_recording.xml come questo.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="180dp"
android:layout_alignParentBottom="true"
android:background="#231f20" >
<ali.visualiser.VisualizerView
android:id="@+id/visualizer"
android:layout_width="220dp"
android:layout_height="75dp"
android:layout_centerHorizontal="true"
android:layout_margin="5dp" />
<TextView
android:id="@+id/txtRecord"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="25dp"
android:gravity="center"
android:text="Start Recording"
android:textColor="@android:color/white"
android:textSize="30sp" />
</RelativeLayout>
Creare un visualizerView personalizzato come indicato di seguito.
package ali.visualiser;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class VisualizerView extends View {
private static final int LINE_WIDTH = 1; // width of visualizer lines
private static final int LINE_SCALE = 75; // scales visualizer lines
private List<Float> amplitudes; // amplitudes for line lengths
private int width; // width of this View
private int height; // height of this View
private Paint linePaint; // specifies line drawing characteristics
// constructor
public VisualizerView(Context context, AttributeSet attrs) {
super(context, attrs); // call superclass constructor
linePaint = new Paint(); // create Paint for lines
linePaint.setColor(Color.GREEN); // set color to green
linePaint.setStrokeWidth(LINE_WIDTH); // set stroke width
}
// called when the dimensions of the View change
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
width = w; // new width of this View
height = h; // new height of this View
amplitudes = new ArrayList<Float>(width/LINE_WIDTH);
}
// clear all amplitudes to prepare for a new visualization
public void clear() {
amplitudes.clear();
}
// add the given amplitude to the amplitudes ArrayList
public void addAmplitude(float amplitude) {
amplitudes.add(amplitude); // add newest to the amplitudes ArrayList
// if the power lines completely fill the VisualizerView
if (amplitudes.size() * LINE_WIDTH >= width) {
amplitudes.remove(0); // remove oldest power value
}
}
// draw the visualizer with scaled lines representing the amplitudes
@Override
public void onDraw(Canvas canvas) {
int middle = height/2; // get the middle of the View
float curX = 0; // start curX at zero
// for each item in the amplitudes ArrayList
for (float power : amplitudes) {
float scaledHeight = power/LINE_SCALE; // scale the power
curX += LINE_WIDTH; // increase X by LINE_WIDTH
// draw a line representing this item in the amplitudes ArrayList
canvas.drawLine(curX, middle + scaledHeight/2, curX, middle
- scaledHeight/2, linePaint);
}
}
}
Creare la classe RecordingActivity come indicato di seguito.
pacchetto ali.visualiser;
import java.io.File;
import java.io.IOException;
import android.app.Activity;
import android.media.MediaRecorder;
import android.media.MediaRecorder.OnErrorListener;
import android.media.MediaRecorder.OnInfoListener;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
public class RecordingActivity extends Activity {
public static final String DIRECTORY_NAME_TEMP = "AudioTemp";
public static final int REPEAT_INTERVAL = 40;
private TextView txtRecord;
VisualizerView visualizerView;
private MediaRecorder recorder = null;
File audioDirTemp;
private boolean isRecording = false;
private Handler handler; // Handler for updating the visualizer
// private boolean recording; // are we currently recording?
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recording);
visualizerView = (VisualizerView) findViewById(R.id.visualizer);
txtRecord = (TextView) findViewById(R.id.txtRecord);
txtRecord.setOnClickListener(recordClick);
audioDirTemp = new File(Environment.getExternalStorageDirectory(),
DIRECTORY_NAME_TEMP);
if (audioDirTemp.exists()) {
deleteFilesInDir(audioDirTemp);
} else {
audioDirTemp.mkdirs();
}
// create the Handler for visualizer update
handler = new Handler();
}
OnClickListener recordClick = new OnClickListener() {
@Override
public void onClick(View v) {
if (!isRecording) {
// isRecording = true;
txtRecord.setText("Stop Recording");
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(audioDirTemp + "/audio_file"
+ ".mp3");
OnErrorListener errorListener = null;
recorder.setOnErrorListener(errorListener);
OnInfoListener infoListener = null;
recorder.setOnInfoListener(infoListener);
try {
recorder.prepare();
recorder.start();
isRecording = true; // we are currently recording
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
handler.post(updateVisualizer);
} else {
txtRecord.setText("Start Recording");
releaseRecorder();
}
}
};
private void releaseRecorder() {
if (recorder != null) {
isRecording = false; // stop recording
handler.removeCallbacks(updateVisualizer);
visualizerView.clear();
recorder.stop();
recorder.reset();
recorder.release();
recorder = null;
}
}
public static boolean deleteFilesInDir(File path) {
if(path.exists()) {
File[] files = path.listFiles();
if (files == null) {
return true;
}
for(int i=0; i<files.length; i++) {
if(files[i].isDirectory()) {
}
else {
files[i].delete();
}
}
}
return true;
}
@Override
protected void onDestroy() {
super.onDestroy();
releaseRecorder();
}
// updates the visualizer every 50 milliseconds
Runnable updateVisualizer = new Runnable() {
@Override
public void run() {
if (isRecording) // if we are already recording
{
// get the current amplitude
int x = recorder.getMaxAmplitude();
visualizerView.addAmplitude(x); // update the VisualizeView
visualizerView.invalidate(); // refresh the VisualizerView
// update in 40 milliseconds
handler.postDelayed(this, REPEAT_INTERVAL);
}
}
};
}
Risultato
Questo è come appare: https://www.youtube.com/watch?v=BoFG6S02GH0
Quando si raggiunge la fine, l'animazione continua come previsto: cancellare l'inizio del grafico.
C'è qualche codice di esempio? – user1972690
Non ho alcun codice di esempio per questo. Ma la maggior parte di esso sembrerebbe una semplice codifica dell'interfaccia utente di Android. Avviare un 'Handler' che [si esegue periodicamente] (http://stackoverflow.com/questions/6242268/repeat-a-task-with-a-time-delay/6242292#6242292), chiamare il metodo' getMaxAmplitude' per il tuo 'MediaRecorder' per ottenere il livello di picco corrente, aggiorna il' View' che contiene le barre del volume in base al nuovo livello di picco, e infine fai un [postInvalidate] (http://stackoverflow.com/questions/5521596/what- does-postinvalidate-do) per richiedere che la Vista modificata sia ridisegnata. – Michael
@Michael Questo sembra avere molto senso, non sono sicuro di quale id audioSession utilizzare per inizializzare il Visualizer. –