I'm a complete noob . I've managed to write and understand this code after reading this http://developer.android.com/guide/topics/media/camera.html .
But now i want to get the byte array for preview and then convert it to bitmap . But i want to do this in real time without be forced to save a picture file in storage . Please , help!
Here is my program code.
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
String TAG = null;
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
mCamera.setDisplayOrientation(90);
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
String TAG = null;
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
private PictureCallback mPicture = new PictureCallback(){
#Override
public void onPictureTaken(byte[] data, Camera camera)
{
// TODO: Implement this method
}
};
}
And main activity :
public class MainActivity extends Activity
{ private Camera mCamera;
private CameraPreview mPreview;
int i;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mCamera = getCameraInstance();
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.frame);
preview.addView(mPreview);
}
public static Camera getCameraInstance()
{
Camera c = null;
try
{
c = Camera.open();}
catch (Exception e)
{ System.out.println("blamjjjh");}
return c;
}
public void releasec(){
mCamera.release();
}
#Override
protected void onStop()
{
super.onStop();
releasec();
}
}
As detailed in the Android Developer docs here (which you might have already read), add an implementation of the PictureCallback interface (see the example below) to your Activity. Also you can use BitmapFactory to then convert the byte array that gets passed back to a Bitmap. Then you can use this as required.
NOTE:
I would also read the docs here on handling Bitmaps efficiently in relation to memory as you might get OutOfMemory errors if you're manipulating Bitmaps.
private PictureCallback mPicture = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
//create a Bitmap from the byte array
Bitmap bitmap = BitmapFactory.decodeByteArray(data , 0, data.length);
//use your Bitmap
}
};
You then need to pass this into the takePicture() method against your camera instance e.g.
// Add a listener to the Capture button
Button captureButton = (Button) findViewById(id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
// get an image from the camera
mCamera.takePicture(null, null, mPicture);
}
}
);
Hope this helps! :-)
Related
I am working on how to apply live wallpaper(GIF image). When I click on apply button the default gif image set as wallpaper. I'm getting all the images from firebase. So I want to set that image as wallpaper. I don't know how to pass that gif image from LiveViewActivity to GIFWallpaperService to set that .gif image as live wallpaper instead of default image. (sorry for my bad English, hope you understand)
LiveWallpaperActivity.java //main activity(where I'm getting all the images from firebase)
|
| //pass the .gif image url by intent to next activity
|
LiveViewActivity.java
|
|
| //Here I receive the image by intent and load into imageview with glide
|
| //added a button to apply live wallpaper(.gif image)
| //pass .gif image to GIFWallpaperService class service (I don't know how to do)
|
GIFWallpaperService
LiveViewActivity
Where i add a button to apply live wallpaper
here i want to pass that .gif image to GIFWallpaperService
public class LiveViewActivity extends AppCompatActivity {
ImageView imageView;
Button setLiveWallpaper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live_view);
imageView = findViewById(R.id.viewImage);
Glide.with(this).load(getIntent().getStringExtra("images")).into(imageView);
setLiveWallpaper.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
applyLiveWallpaper();
}
});
}
private void applyLiveWallpaper() {
Intent intent = new Intent(
WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
new ComponentName(this, GIFWallpaperService.class));
startActivity(intent);
}
}
GIFWallpaperService
here I want to receive .gif image that I send from LiveViewActivity
to set as live wallpaper
public class GIFWallpaperService extends WallpaperService {
#Override
public WallpaperService.Engine onCreateEngine() {
try {
Movie movie = Movie.decodeStream(getResources().getAssets().open("sea_gif.gif")); //Here is the default gif image
return new GIFWallpaperEngine(movie);
} catch (IOException e) {
Log.d("GIFWallpaperService", "Could not loaded live wallpaper");
return null;
}
}
private class GIFWallpaperEngine extends WallpaperService.Engine {
private final int frameDuration = 20;
private SurfaceHolder holder;
private Movie movie;
private boolean visible;
private Handler handler;
public GIFWallpaperEngine(Movie movie) {
this.movie = movie;
handler = new Handler();
}
#Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
this.holder = surfaceHolder;
}
private Runnable drawGIF = new Runnable() {
#Override
public void run() {
draw();
}
};
private void draw() {
if (visible) {
Canvas canvas = holder.lockCanvas();
canvas.save();
canvas.scale(4f, 4f);
movie.draw(canvas, -100, 0);
canvas.restore();
holder.unlockCanvasAndPost(canvas);
movie.setTime((int) (System.currentTimeMillis() % movie.duration()));
handler.removeCallbacks(drawGIF);
handler.postDelayed(drawGIF, frameDuration);
}
}
#Override
public void onVisibilityChanged(boolean visible) {
//super.onVisibilityChanged(visible);
this.visible = visible;
if (visible) {
handler.post(drawGIF);
} else {
handler.removeCallbacks(drawGIF);
}
}
#Override
public void onDestroy() {
super.onDestroy();
handler.removeCallbacks(drawGIF);
}
}
}
I don't know how to send and receive .gif image from LiveViewActivity to GIFWallpaperService
Your question is a little misty to me, but If I get you right, actually you can easily get the picture in LiveWallpaperActivity through the adapter by the context and then from this activity you can pass your image to whatever activity you want by intent.
To send a data from an activity to a service, you need to override onStartCommand there you have direct access to intent:
Override
public int onStartCommand(Intent intent, int flags, int startId) {
then from LiveViewActivity you will create the intent object to start service and then you place your image name inside the intent object :
Intent serviceIntent = new Intent(YourService.class.getName())
serviceIntent.putExtra("IMAGE_KEY", "image");
context.startService(serviceIntent);
When the service is started its onStartCommand() method will be called then you can get the image:
public int onStartCommand (Intent intent, int flags, int startId) {
String image = intent.getStringExtra("IMAGE_KEY");
return START_STICKY;
}
Try using DomainEventBus which helps in passing objects, images, and in fact any data types across all the applications.
https://greenrobot.org/eventbus/
With this, you need to register the "event bus" on creation of service and it will be able to receive the image from any component of the application.
I'm new in android.
I found previous questions, but are quite old, actually I'm using API 23 or higher.
I'm interested in a way to obtaining a picture from a camera, without displaying the preview and without any touch or interaction of the user.
I used an intent to access to a camera app but don't let me to take a picture automatically in the way I need.
This only let me to use camera app.
Intent intentTakePic = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if(intentTakePic.resolveActivity(getPackageManager()) != null){
startActivityForResult(intentTakePic, GET_THE_PICTURE);
}
In future I probably need also to record the audio in the same way (without interaction).
Does anyone has suggestion for me ?
You need to use the CameraAPI to take pictures without opening another camera app. https://developer.android.com/guide/topics/media/camera
You'll basically make a camera app.
// in the activity onCreate, but doesn't have to be there
// needs explicit permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[] {Manifest.permission.CAMERA}, 1);
}
}
final Camera camera = Camera.open();
CameraPreview cameraPreview = new CameraPreview(this, camera);
// preview is required. But you can just cover it up in the layout.
FrameLayout previewFL = findViewById(R.id.preview_layout);
previewFL.addView(cameraPreview);
camera.startPreview();
// take picture button
findViewById(R.id.take_picture_button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
camera.takePicture(null, null, new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
// path of where you want to save it
File pictureFile = new File(getFilesDir() + "/images/pic0");
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
});
CameraPreview class
import android.content.Context;
import android.hardware.Camera;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
e.printStackTrace();
}
}
}
I found these useful guide:
https://zatackcoder.com/android-camera-2-api-example-without-preview/
https://inducesmile.com/android/android-camera2-api-example-tutorial/
https://github.com/googlesamples/android-Camera2Basic
I have made an imageView animate from one side to the other side of the screen. Here is the java code:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageView imageView = findViewById(R.id.imageView);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
handleAnimation(imageView);
}
});
}
public void handleAnimation(View view) {
ObjectAnimator animatorX = ObjectAnimator.ofFloat(view, "x", 1000f);
animatorX.setDuration(2000);
animatorX.start();
}
}
And this is what we see when user clicks on the ANIMATE button:
Now my question is that how I can make a video file by capturing the animated imageView ?
EDIT:
What I need is: I want to make an app which takes some photos from the user and make some animations on the photos and some effects and also mix them with a desired sound and at the end exports a video clip. And of course if I can I would rather make all these things hidden.
You have to record your screen and then crop the video using your view's xy coordinates. You can record your screen using the MediaProject API on android (5) and above.
private VirtualDisplay mVirtualDisplay;
private MediaRecorder mMediaRecorder;
private MediaProjection mMediaProjection;
private MediaProjectionCallback callback;
MediaProjectionManager projectionManager = (MediaProjectionManager)
context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
mMediaProjection.registerCallback(callback, null);
initRecorder();
mMediaRecorder.prepare();
mVirtualDisplay = createVirtualDisplay();
mMediaRecorder.start();
public void initRecorder() {
path = "/sdcard/Record/video" + ".mp4";
recId = "capture-" + System.currentTimeMillis() + ".mp4";
File myDirectory = new File(Environment.getExternalStorageDirectory(), "Record");
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setVideoEncodingBitRate(MainFragment.bitRate);
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoSize(MainFragment.DISPLAY_WIDTH,
MainFragment.DISPLAY_HEIGHT);
mMediaRecorder.setOutputFile(path);
}
private VirtualDisplay createVirtualDisplay() {
return mMediaProjection.createVirtualDisplay("MainActivity",
MainFragment.DISPLAY_WIDTH, MainFragment.DISPLAY_HEIGHT, MainFragment.screenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mMediaRecorder.getSurface(), null /*Callbacks*/, null /*Handler*/);
}
public class MediaProjectionCallback extends MediaProjection.Callback {
#Override
public void onStop() {
mMediaRecorder.stop();
// mMediaRecorder.reset();
mMediaRecorder.release();
mMediaProjection.unregisterCallback(callback);
mMediaProjection = null;
mMediaRecorder = null;
}
Once done simply call mMediaProjection.stop() to finish the recording and save the video as tmp
After which you can crop the video at the xy coordinates that your view is position using FFmpeg
ffmpeg -i in.mp4 -filter:v "crop=out_w:out_h:x:y" out.mp4
Where the options are as follows:
out_w is the width of the output rectangle
out_h is the height of the output rectangle
x and y specify the top left corner of the output rectangle
so in your case
String cmd ="-i '"+ tmpVideoPath+"' -filter:v "+"'crop="+view.getWidth()+":"+view.getHeight()+":"+view.getX()+":"+view.getY()+"'"+" -c:a copy "+outVideoPath
FFmpeg ffmpeg = FFmpeg.getInstance(context);
// to execute "ffmpeg -version" command you just need to pass "-version"
ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
#Override
public void onStart() {}
#Override
public void onProgress(String message) {}
#Override
public void onFailure(String message) {}
#Override
public void onSuccess(String message) {}
#Override
public void onFinish() {}
});
There are two possible approaches to archive this.
1- You can acchive this by using the javacv library (FFmpeg) to combine a set of bitmaps taken from the view
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder("/sdcard/test.mp4",256,256);
try {
recorder.setVideoCodec(avcodec.AV_CODEC_ID_MPEG4);
recorder.setFormat("mp4");
recorder.setFrameRate(30);
recorder.setPixelFormat(avutil.PIX_FMT_YUV420P10);
recorder.setVideoBitrate(1200);
recorder.startUnsafe();
for (int i=0;i< 5;i++)
{
view.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
view.setDrawingCacheEnabled(false);
recorder.record(bitmap);
}
recorder.stop();
}
catch (Exception e){
e.printStackTrace();
}
all the code of using this library is here
2- You can use this link for record the screen and use as per your need.
Screen Recorder
New to Android programming here.
I have had a look around and have found this to be a common issue, but I don't really see an easy fix... I am trying to run the following code on a Nexus 7 (have tried AVD & physical device) with no luck whatsoever. It seems to be the:
camera.setPreviewDisplay(SurfaceHolder);
But I could be wrong. Here is the current code:
public class MainActivity extends Activity implements SurfaceHolder.Callback{
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean previewing = false;;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.cameralayout);
getWindow().setFormat(PixelFormat.UNKNOWN);
surfaceView = (SurfaceView)findViewById(R.id.surfaceview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
}
public void onClick() {
// TODO Auto-generated method stub
if(!previewing){
camera = Camera.open();
if (camera != null){
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
previewing = true;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Any ideas folks? Thank you for your help!
From android documentation about Camera.open()
Creates a new Camera object to access the first back-facing camera on
the device. If the device does not have a back-facing camera, this
returns null.
It gives you only an access to back-facing Camera.
I am trying to run the following code on a Nexus 7
Camera.open() returns null because Nexus 7 doesn't have a back camera, only a front camera.
You could try this method
public Camera getCamera()
{
for(int i = 0; i < Camera.getNumberOfCameras(); i++)
return Camera.open(i);
return null;
}
To apply,
camera = getCamera();
I'm using a Nexus One and the Camera displays horizontal when it should be vertical and vice versa. I've no idea what's wrong. The code works fine on a HTC tattoo. Anyone have any idea what's wrong?
class Preview extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder mHolder;
Camera mCamera;
Preview(Context context) {
super(context);
// Install a SurfaceHolder.Callback so we get notified when
//the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell
//it where
// to draw.
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return, so stop the
//preview.
// Because the CameraDevice object is not a shared resource,
//it's very
// important to release it when the activity is paused.
mCamera.stopPreview();
mCamera = null;
}
public void surfaceChanged(SurfaceHolder holder, int format, int
w, int h) {
// Now that the size is known, set up the camera parameters
//and begin
// the preview.
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(800, 480);
mCamera.setParameters(parameters);
mCamera.startPreview();
}
Got it working. I added..
parameters.set("orientation", "portrait");
CommonsWare gave me the idea it was that kind of issue thanks man :)