Original address: http://blog.csdn.net/sinat_35845281/article/details/52674946
I've been trying to get a novelty.
Recently has been learning to share webcam data through two Android phones via WiFi. It took a long time to get some bosses. Here are a few steps:
1. For mobile phone camera development, customize the Surfaceview to define your own camera class. The main display is the screen of the mobile phone camera.
2. Get the data for the preview screen of the custom camera. The data is then parsed.
3. Establish a connection between two Android phones to transmit data over WiFi.
4. Transfer the data from one to two phones.
I. Custom camera class It is very simple to define a surfaceview, in activity, by implementing the Surfacehodler.callback Interface rewrite onsurfacecreate () You can get a camera object by adding the Camera.open that opens the cameras. Sets the preview object for the camera. Mcamera.setpreviewdisplay (holder); Holder is the hodler of our surfaceview. can be obtained by Surfaceview.gethodler (). This will display the preview of our phone in Surfaceview.
The code is as follows:
package com.weipu.camera;
import java.io.IOException;
import android.annotation.TargetApi;
import android.app.Activity;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
* *
*Interface surfaceholder.callback is used to receive the information about the changes of camera preview interface. It implements three methods: surfacechanged
*This method is called when the format and size of the preview interface change. When surfacecreated is instantiated for the first time and the preview interface is created, this method is called.
*Surfacetestroyed this method is called when the preview interface is closed.
*
* @author pengqinping
* /
@TargetApi(9)
public class MyCameraActivity extends Activity implements
SurfaceHolder.Callback, OnClickListener
{
private SurfaceHolder mSurfaceHolder = null;
private SurfaceView mSurfaceView = null;
private Camera mCamera = null;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Initializing components, surfaceview
mSurfaceView = (SurfaceView) findViewById(R.id.SurfaceView01);
* *
*Through the code, we get the holder from the surface view and add the callback function to "this".
*This means that our activity will be able to manage the surface view.
* /
Msurfaceholder = msurfaceview. Getholder(); / / get the holder object of surfaceview
Msurfaceholder. Addcallback (this); / / add a callback function for the holder object of surfaceview,
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
protected void onStart()
{
super.onStart();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width1,
Int height1)
{
if (mCamera == null)
{
System. Out. Println ("no camera device");
Return;
}
if (mCamera != null)
{
//Initialize the camera. Setting parameters
Camera.Parameters parameters = mCamera.getParameters();
Parameters. Setpreviewsize (width1, high1); / / set the size of preview photos
Parameters. Setpreviewfpsrange (20, 30); / / display 20-30 frames per second
Parameters. Setpictureformat (imageformat. Nv21); / / set picture format
Parameters. Setpicturesize (width 1, height 1); / / set the size of the photo
}
Try
{
mCamera.setPreviewDisplay(holder);
}
catch (IOException e)
{
System. Out. Println ("setting preview error...);
}
//Display viewfinder through surfaceview
Mcamera. Startpreview(); / / start Preview
Mcamera. Autofocus (null); / / autofocus
}
@Override
public void surfaceCreated(SurfaceHolder holder)
{
Try
{
mCamera = Camera.open();
}
catch (Exception e)
{
System.out.println("000000000");
Return;
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
mCamera.stopPreview();
mCamera.release();
}
@Override
public void onClick(View v)
{
}
}
Here, you need to add the androidmanifest.xml in the corresponding activity statement.
Android:configchanges= "Keyboardhidden|orientation"
android:screenorientation= "Landscape"
Example: (This is to set his landscape and horizontal screen changes in the activity to make changes)
<activity
android:name=".CameraDemophotoneActivity"
android:configChanges="keyboardHidden|orientation"
android:label="@string/app_name"
android:screenOrientation="landscape" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
In terms of permissions, it is best to add network permissions:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
Two. How to get the data of the mobile phone preview, how to get the phone camera? Preview function via callback phone: Mcamera.setpreviewcallback (streamit); An object that streamit the interface of the callback. So we can get the data from the camera preview. Obtained is the original data in YUV format. The key to this step is how the parsing of the data is decoded. I wrote it on the internet and I copied it. The important thing is to decide how to use it according to your own needs, I use the second kind, the comparison is not easy to make mistakes. The first kind of effect is poor, here the code I will not get out. (Just use the good .....>>>> haha hehe)
The code is as follows:
private Camera.PreviewCallback streamIt = new Camera.PreviewCallback()
{
@Override
public void onPreviewFrame(byte[] data, Camera camera)
{
//Method1: use decode
//Method2: use the system's own class to send pictures
Size size = camera. Getparameters(). Getpreviewsize(); / / get size
Try
{
//Call image. Compresstojpeg() to change image data in YUV format to JPG format
YuvImage image = new YuvImage(data, ImageFormat.NV21,
size.width, size.height, null);
//Use handler to send pictures out
ByteArrayOutputStream outputSteam = new ByteArrayOutputStream();
image.compressToJpeg(new Rect(0, 0, size.width, size.height),
80,
outputSteam);
}
catch (Exception ex)
{
Log.e("Sys", "Error:" + ex.getMessage());
}
}
}
Three, two phones to establish a connection between. Via WiFi LAN, not necessarily wifi. As long as in a network segment can, this step I because of the reasons for the equipment to go a lot of detours. At first I was using the simulator to operate, because the simulator does not specify the IP also must be through the port mapping to complete, finally the port mapping is done, he two simulator with port mapping seems inappropriate, because in the test when the emulator itself uses the same port, the problem is more. I failed many times and then used the real machine test directly, through WiFi, and thanks to my colleagues for providing their own device testing. This step needs to be noted that when the Android phone opens a port when there is a blocking method we'd better put in the thread to open, after accepting the data we can not update the interface data, this is the location of Android in the more headache. We also need to do this through the threading helper class.
Four. The idea of data sharing.
Mobile data Start-up (connect to the specified IP side); Turn on a thread to send the data, because sending directly in Android causes a lot of problems with the main thread.
The phone accepts the data side (that is, the device that opens the port waiting to receive data). Can be a thread to accept the data, after receiving the data through the handler to follow the new phone display screen.
Android mobile camera data sharing via WiFi hotspot (GO)