Image Processing
Efficiently loading large images requires calculating a sample size to avoid memory overflow (OutOfMemoryError). By setting inJustDecodeBounds to true, you can retrieve image dimensions without loading the pixel data into memory.
public void scaleImage(String path, int targetWidth, int targetHeight) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, opts);
int scale = 1;
int widthRatio = opts.outWidth / targetWidth;
int heightRatio = opts.outHeight / targetHeight;
if (widthRatio > 1 || heightRatio > 1) {
scale = Math.max(widthRatio, heightRatio);
}
opts.inSampleSize = scale;
opts.inJustDecodeBounds = false;
Bitmap result = BitmapFactory.decodeFile(path, opts);
imageView.setImageBitmap(result);
}
To manipulate images—such as rotation, reflection, or creating oevrlays—use Canvas and Matrix classes. Working on a mutable copy of the bitmap preserves the original source.
Bitmap base = BitmapFactory.decodeResource(getResources(), R.drawable.source);
Bitmap mutableCopy = base.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(mutableCopy);
Matrix transformation = new Matrix();
// Create reflection
transformation.setScale(1, -1);
transformation.postTranslate(0, base.getHeight());
canvas.drawBitmap(base, transformation, new Paint());
Audio Playback with Service
For persistent audio playback, encapsulate MediaPlayer within a Service. Use a Binder to communicate progress and playback states between the UI and the service.
public class AudioService extends Service {
private MediaPlayer player;
public void play(String dataSource) {
player.reset();
player.setDataSource(dataSource);
player.prepare();
player.start();
}
// Use a Handler in the Activity to update SeekBars based on currentPosition
private void updateProgress() {
int current = player.getCurrentPosition();
// Send message to UI thread
}
}
Video Rendering
Android provides two primary methods for video playback: SurfaceView for full manual control and VideoView for rapid implementation.
Using SurfaceView
SurfaceView allows the media player to render frames directly to a dedicated surface. Always ensure resources are released in the surfaceDestroyed callback.
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) {
mediaPlayer.setDisplay(holder);
mediaPlayer.prepareAsync();
}
public void surfaceDestroyed(SurfaceHolder holder) {
if (mediaPlayer != null) mediaPlayer.release();
}
});
Using VideoView
VideoView simplifies the process by abstracting the MediaPlayer and SurfaceView setup.
VideoView videoView = findViewById(R.id.video_player);
videoView.setVideoPath("https://example.com/video.mp4");
videoView.start();
Capturing Media via Intents
Leverage stendard system intents to delegate camera operations to dedicated system applications.
public void launchCamera(String fileName) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File storage = new File(Environment.getExternalStorageDirectory(), fileName);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(storage));
startActivityForResult(intent, REQUEST_CODE_CAMERA);
}