Android System
📸 Camera Usage Method
Accessing the camera can typically be achieved through the Camera2 API or the legacy Camera API. The following is a basic code example using the Camera2 API to access the camera:
1. Add Permissions
Add the required permissions in AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
2. Check Camera Permissions
After installing the App, you can enter system settings to grant the App's camera access permission by default, avoiding prompts needed during use.
3. Create Camera2 API Configuration
First, you need to obtain the device's camera information and open the camera:
public class CameraActivity extends AppCompatActivity {
private CameraDevice mCameraDevice;
private CameraCaptureSession mCaptureSession;
private CameraCharacteristics mCameraCharacteristics;
private String mCameraId;
private static final int REQUEST_CAMERA_PERMISSION = 200;
private CameraManager mCameraManager;
// Change SurfaceView to TextureView if needed
private TextureView mSurfaceView;
private Surface mSurface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
mSurfaceView = findViewById(R.id.surfaceView);
mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
// Get the camera IDs supported by the device
for (String cameraId : mCameraManager.getCameraIdList()) {
mCameraCharacteristics = mCameraManager.getCameraCharacteristics(cameraId);
Integer facing = mCameraCharacteristics.get(CameraCharacteristics.LENS_FACING);
// Use front camera by default, choose camera based on actual needs
if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
mCameraId = cameraId;
break;
}
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
openCamera();
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
}
}
@RequiresPermission(Manifest.permission.CAMERA)
private void openCamera() {
try {
mCameraManager.openCamera(mCameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
mCameraDevice = camera;
createCameraPreviewSession();
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
camera.close();
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
camera.close();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void createCameraPreviewSession() {
try {
SurfaceTexture surfaceTexture = mSurfaceView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(1920, 1080);
mSurface = new Surface(surfaceTexture);
// Configure preview request
CaptureRequest.Builder previewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
previewRequestBuilder.addTarget(mSurface);
mCameraDevice.createCaptureSession(Arrays.asList(mSurface), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
if (mCameraDevice == null) return;
mCaptureSession = session;
try {
// Start displaying preview
mCaptureSession.setRepeatingRequest(previewRequestBuilder.build(), null, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
Toast.makeText(CameraActivity.this, "Configuration failed", Toast.LENGTH_SHORT).show();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
protected void onPause() {
super.onPause();
if (mCameraDevice != null) {
mCameraDevice.close();
mCameraDevice = null;
}
}
}
4. Layout File
Add a SurfaceView in activity_camera.xml to display the camera preview:
<TextureView
android:id="@+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
5. Close Camera When Finished
Close the camera device in the onPause() method:
@Override
protected void onPause() {
super.onPause();
if (mCameraDevice != null) {
mCameraDevice.close();
mCameraDevice = null;
}
}
🎙 Microphone Usage Method
Using the microphone for audio capture can typically be achieved through MediaRecorder or AudioRecord. MediaRecorder is more suitable for audio recording, while AudioRecord provides lower-level control, suitable for scenarios requiring fine-grained control over audio capture.
Method 1: Simple Audio Recording Using MediaRecorder
MediaRecorder is a high-level interface, suitable for audio recording operations, simple and easy to use.
Step 1: Add Permissions
Add recording permissions in the AndroidManifest.xml file:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.microphone" />
Step 2: Initialize MediaRecorder
Create and configure MediaRecorder in the code:
public class AudioRecorderActivity extends AppCompatActivity {
private MediaRecorder mediaRecorder;
private String audioFilePath;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_audio_recorder);
// Declare button variables
Button startButton = findViewById(R.id.startButton);
Button stopButton = findViewById(R.id.stopButton);
// Set audio save path
audioFilePath = getExternalFilesDir(null).getAbsolutePath() + "/audio_record.aac";
// Initialize MediaRecorder
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // Use microphone as audio source
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); // Set audio file format
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // Set audio encoding method
mediaRecorder.setOutputFile(audioFilePath); // Set output file path
// Step 2: Set click event for start recording button
startButton.setOnClickListener(v -> {
// Call method to start recording
Log.i("wtf","startRecording");
startRecording();
});
// Step 3: Set click event for stop recording button
stopButton.setOnClickListener(v -> {
// Call method to stop recording
Log.i("wtf","stopRecording");
stopRecording();
});
}
// Start recording
public void startRecording() {
try {
mediaRecorder.prepare(); // Prepare recording
mediaRecorder.start(); // Start recording
} catch (IOException e) {
System.out.print("Startup exception");
e.printStackTrace();
}
}
// Stop recording
public void stopRecording() {
try {
mediaRecorder.stop(); // Stop recording
mediaRecorder.release(); // Release resources
} catch (RuntimeException e) {
e.printStackTrace();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mediaRecorder != null) {
mediaRecorder.release(); // Ensure resource release
}
}
}
Step 3: Start and Stop Recording
You can control the start and stop of recording through buttons or other controls, for example:
Button startButton = findViewById(R.id.startButton);
Button stopButton = findViewById(R.id.stopButton);
startButton.setOnClickListener(v -> startRecording());
stopButton.setOnClickListener(v -> stopRecording());
Method 2: Low-Latency Audio Recording Using AudioRecord
If you need more precise audio control, AudioRecord is a lower-level interface suitable for real-time audio processing.
Step 1: Add Permissions
Also need to add recording permissions in the AndroidManifest.xml file:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-feature android:name="android.hardware.microphone" />
Step 2: Initialize AudioRecord
public class AudioRecorderActivity extends AppCompatActivity {
private static final int SAMPLE_RATE_IN_HZ = 44100; // Sample rate
private AudioRecord audioRecord;
private boolean isRecording = false;
private Thread recordingThread;
private String audioFilePath;
private FileOutputStream fileOutputStream; // File output stream
@Override
@RequiresPermission(Manifest.permission.RECORD_AUDIO)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_audio_recorder);
// Declare button variables
Button startButton = findViewById(R.id.startButton);
Button stopButton = findViewById(R.id.stopButton);
// AudioRecord initialization
int bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE_IN_HZ, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
SAMPLE_RATE_IN_HZ,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize);
// Audio recording thread
recordingThread = new Thread(new Runnable() {
@Override
public void run() {
recordAudio();
}
});
startButton.setOnClickListener(v -> {
// Call method to start recording
Log.i("wtf","startRecording");
startRecording();
});
// Step 3: Set click event for stop recording button
stopButton.setOnClickListener(v -> {
// Call method to stop recording
Log.i("wtf","stopRecording");
stopRecording();
});
}
// Start recording
public void startRecording() {
audioRecord.startRecording();
isRecording = true;
recordingThread.start();
}
// Stop recording
public void stopRecording() {
isRecording = false;
audioRecord.stop();
audioRecord.release();
}
private void recordAudio() {
// Create audio file path (in private directory of external storage)
String audioFileName = "audio_record_" + System.currentTimeMillis() + ".wav";
File audioFile = new File(getExternalFilesDir(null), audioFileName);
audioFilePath = audioFile.getAbsolutePath(); // Save file path to member variable
byte[] audioBuffer = new byte[1024];
int totalBytesRead = 0;
try (FileOutputStream fos = new FileOutputStream(audioFile)) {
// First write WAV file header (placeholder, fill actual values later)
writeWavHeader(fos, 0, 0);
while (isRecording) {
int read = audioRecord.read(audioBuffer, 0, audioBuffer.length);
if (read > 0) {
// Write audio data to file
fos.write(audioBuffer, 0, read);
totalBytesRead += read;
}
}
// After recording is complete, update the actual data size in the WAV file header
updateWavHeader(audioFile, totalBytesRead);
} catch (IOException e) {
Log.e("AudioRecord", "File write failed: " + e.getMessage());
}
}
// Write WAV file header (initial placeholder version)
private void writeWavHeader(FileOutputStream out, long totalAudioLen, long totalDataLen) throws IOException {
long sampleRate = SAMPLE_RATE_IN_HZ;
int channels = 1; // Mono
int bitsPerSample = 16; // 16-bit
byte[] header = new byte[44];
// RIFF/WAVE header
header[0] = 'R'; header[1] = 'I'; header[2] = 'F'; header[3] = 'F';
header[4] = (byte) (totalDataLen & 0xff);
header[5] = (byte) ((totalDataLen >> 8) & 0xff);
header[6] = (byte) ((totalDataLen >> 16) & 0xff);
header[7] = (byte) ((totalDataLen >> 24) & 0xff);
// WAVE
header[8] = 'W'; header[9] = 'A'; header[10] = 'V'; header[11] = 'E';
// 'fmt ' chunk
header[12] = 'f'; header[13] = 'm'; header[14] = 't'; header[15] = ' ';
// 4 bytes: size of 'fmt ' chunk
header[16] = 16; header[17] = 0; header[18] = 0; header[19] = 0;
// format = 1 (PCM)
header[20] = 1; header[21] = 0;
// number of channels
header[22] = (byte) channels; header[23] = 0;
// sample rate
header[24] = (byte) (sampleRate & 0xff);
header[25] = (byte) ((sampleRate >> 8) & 0xff);
header[26] = (byte) ((sampleRate >> 16) & 0xff);
header[27] = (byte) ((sampleRate >> 24) & 0xff);
// byte rate
long byteRate = sampleRate * channels * bitsPerSample / 8;
header[28] = (byte) (byteRate & 0xff);
header[29] = (byte) ((byteRate >> 8) & 0xff);
header[30] = (byte) ((byteRate >> 16) & 0xff);
header[31] = (byte) ((byteRate >> 24) & 0xff);
// block align
header[32] = (byte) (channels * bitsPerSample / 8);
header[33] = 0;
// bits per sample
header[34] = (byte) bitsPerSample;
header[35] = 0;
// data chunk
header[36] = 'd'; header[37] = 'a'; header[38] = 't'; header[39] = 'a';
header[40] = (byte) (totalAudioLen & 0xff);
header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
out.write(header, 0, 44);
}
// Update actual data size in WAV file header
private void updateWavHeader(File file, int totalAudioLen) {
try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
// Update total file size (file size - 8)
long totalDataLen = totalAudioLen + 36; // 36 = 44 - 8
raf.seek(4);
raf.write((int) (totalDataLen & 0xff));
raf.write((int) ((totalDataLen >> 8) & 0xff));
raf.write((int) ((totalDataLen >> 16) & 0xff));
raf.write((int) ((totalDataLen >> 24) & 0xff));
// Update audio data size
raf.seek(40);
raf.write((int) (totalAudioLen & 0xff));
raf.write((int) ((totalAudioLen >> 8) & 0xff));
raf.write((int) ((totalAudioLen >> 16) & 0xff));
raf.write((int) ((totalAudioLen >> 24) & 0xff));
} catch (IOException e) {
Log.e("AudioRecord", "Error updating WAV header: " + e.getMessage());
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (audioRecord != null) {
audioRecord.release(); // Ensure resource release
}
}
}
Step 3: Start and Stop Recording
Similarly, use buttons or other controls to control the start and stop of recording:
Button startButton = findViewById(R.id.startButton);
Button stopButton = findViewById(R.id.stopButton);
startButton.setOnClickListener(v -> startRecording());
stopButton.setOnClickListener(v -> stopRecording());
Method 3: Save Recording Data to File
If you wish to save the audio data to a file, you can use the write method of AudioRecord to save the audio stream to a file, or directly use MediaRecorder to save it as a .3gp format file.
Other Considerations
- Permission Issues: Consistent with the camera, it is recommended to enable microphone permission by default through system settings to avoid dynamic permission requests.
- Device Compatibility: Ensure the device supports microphone functionality, check the features of AudioManager and MediaRecorder.
- Thread Management: If using AudioRecord, audio recording needs to be done in a background thread, otherwise it may cause ANR (Application Not Responding).
- If you need simple recording functionality, you can use MediaRecorder.
- If you need finer control (e.g., real-time audio processing), you can use AudioRecord.
🖥️ Screen Display Usage Method
- General Layout Display: Use standard Android layouts to display relevant content on the screen.
- Layout Implementation Method: Use basic Android layout methods or custom UI to achieve display content that meets resolution requirements.
- Circular Screen Adaptation:
- System resolution is 500×500
- The actual effective display area is a circular area with a radius of 250 pixels
- Pay special attention to the boundary adaptation of the circular area during layout.