2018-02-08 14:40:52 xy1213236113 阅读数 7596
  • Android底层技术:HAL驱动开发

    本课程提供开发者学习Android底层的HAL(硬件抽象层)的开发方法和技术。HAL所在的位置是介于Android系统服务与Linux内核之间,HAL Driver是以library形式出现,给HAL Stub调用,供Android System架构者调用。而HAL Stub则是google设计出来的,保护硬件厂商的硬件驱动。

    17825 人正在学习 去看看 高煥堂

使用opencv去访问android设备摄像头, C++库是无法获取到android设备硬件的,所有需要借助Opencv对android提供的java库进行访问android设备摄像头。在opencv官方下载AndroidSDK,导入项目中就可以使用了。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <!--JavaCameraView最终继承自SurfaceView,显示摄像头帧数据的展示-->
    <org.opencv.android.JavaCameraView
        android:id="@+id/cameraView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:camera_id="back"//后置摄像头
        />
</android.support.constraint.ConstraintLayout>

JavaCameraView继承自CameraBridgeViewBase,CameraBridgeViewBase又继承自SurfaceView,JavaCameraView是可以显示摄像头捕获到的帧数据的View,CameraBridgeViewBase类中CvCameraViewListener2接口提供了摄像头onCameraViewStarted、onCameraViewStopped以及onCameraFrame回调。我们要对摄像头捕获的每一帧数据进行操作就需要再OnCameraFrame回调中进行处理。通过一个native函数,在将摄像头的每一帧数据地址传给C++,对帧数据进行操作。代码如下:

public class CameraOpenCVActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener2 {//
    private JavaCameraView cameraView;
    private Mat rgba;
    static {
        System.loadLibrary("native-lib");
    }
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera_opencv);
        cameraView = findViewById(R.id.cameraView);
        cameraView.setCvCameraViewListener(this);
        //权限请求
        RxPermissions rxPermission = new RxPermissions(this);
        rxPermission
                .requestEachCombined(Manifest.permission.CAMERA,
                        Manifest.permission.READ_EXTERNAL_STORAGE)
                .subscribe(permission -> {
                    if (permission.granted) {
                    } else if (permission.shouldShowRequestPermissionRationale) {
                    } else {
                    }
                });
    }
    //NDK对每一帧数据进行操作
    public static native void nativeRgba(long jrgba);

    /**
     *  当摄像机预览开始时,这个方法就会被调用。在调用该方法之后,框架将通过onCameraFrame()回调向客户端发送。
     *
     * @param width  - 帧的宽度
     * @param height - 帧的高度
     */
    @Override
    public void onCameraViewStarted(int width, int height) {
        //定义Mat对象
        rgba = new Mat(width, height, CvType.CV_8UC4);
    }

    /**
     * 当摄像机预览由于某种原因被停止时,这个方法就会被调用。
     *在调用这个方法之后,不会通过onCameraFrame()回调来传递任何帧。
     */
    @Override
    public void onCameraViewStopped() {
        rgba.release();
    }

    /**
     * 当需要完成框架的交付时,将调用此方法。
     *返回值-是一个修改后的帧,需要在屏幕上显示。
     * TODO: pass the parameters specifying the format of the frame (BPP, YUV or RGB and etc)
     *
     * @param inputFrame
     */
    @Override
    public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
        rgba = inputFrame.rgba();
        //得到当前一帧图像的内存地址
        long addr = rgba.getNativeObjAddr();
        //对一帧图像进行处理
        nativeRgba(addr);
        //得到一帧灰度图
//        rgba = inputFrame.gray();
        return rgba;
    }


    @Override
    protected void onResume() {
        super.onResume();
        if (!OpenCVLoader.initDebug()) {
        } else {
            cameraView.enableView();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (cameraView != null) {
            cameraView.disableView();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (cameraView != null) {
            cameraView.disableView();
        }
    }
}

在C++中对每一帧数据进行单通道处理,并做了SobelX和Y方向的边缘检测,代码和结果如下:

 Mat &img = *(Mat*)jrgba;
    Mat out;
    cvtColor(img,out,COLOR_RGBA2GRAY);
    Mat outimgX,outimgY,outXY;
    //x方向sobel梯度
    Sobel(out,outimgX,CV_8U,1,0);
    //y方向sobel梯度
    Sobel(out,outimgY,CV_8U,0,1);
    //合并梯度
    addWeighted(outimgX,0.5,outimgY,0.5,0,outXY);
    uchar *ptr = img.ptr(0);
    uchar *outPtr = outXY.ptr(0);
    for (int i = 0; i < img.rows * img.cols; ++i) {
        ptr[4*i+0] = outPtr[I];
        ptr[4*i+1] = outPtr[I];
        ptr[4*i+2] = outPtr[I];
    }

Screenshot_2018-02-07-23-37-12-648.png

当前我使用的是后置摄像头,我们又发现了一个问题,帧数据是显示出来,但是图像是横着的,怎么正过来呢?很简单,我们既然获取到了每一帧数据的矩阵,那么我们直接就可以对矩阵进行操作。原理与代码如下:

 Mat &img = *(Mat*)jrgba;

    Mat imgT(height,width,CV_8UC4);
    Mat imgF(height,width,CV_8UC4);
//    //图片倒置
    transpose(img,imgT);
    /**
   * 重定义图片大小
   * 第三个参数dsize:size格式的图片大小
   * 第四个参数dx:x方向的图片缩放比
   * 第五个参数dy:y方向的缩放比
   * 第六个参数:插值方式,一般情况使用默认值(线性插值)
   * dsize不为0的时候,dx和dy是无效的
   *
   */
    resize(imgT,imgF,Size(width,height));
    /**
     * 翻转图片
     * 第三个参数,0以x轴进行翻转,1以y轴翻转,-1以xy同时翻转
     */
    flip(imgF,img,1);

Screenshot_2018-02-07-23-30-53-933.png

哈哈!图像正过来了吧!当前是后置摄像头,那么前置摄像头会不会也是这样的解决办法呢?那我们代码撸起,看那看会如何呢?

Screenshot_2018-02-07-23-00-17-594.png

此时我们发现,用于后置摄像头相同的操作去解决,并没有达到预期的效果,很明显图像是倒置的并且左右方向也是反的。于是乎,深思之后,发现前置摄像头与后置摄像头的图像其实就相当于一个照镜子的过程,我们可以在倒置矩阵之后,再进行一次X,Y方向上的同时矩阵翻转,不就可以了,一切想明白了之后,试了试,果然达到了预期目标效果。图像与代码如下:

 Mat &img = *(Mat*)jrgba;
    Mat imgT(height,width,CV_8UC4);
    Mat imgF(height,width,CV_8UC4);
//    //图片倒置
    transpose(img,imgT);
    /**
   * 重定义图片大小
   * 第三个参数dsize:size格式的图片大小
   * 第四个参数dx:x方向的图片缩放比
   * 第五个参数dy:y方向的缩放比
   * 第六个参数:插值方式,一般情况使用默认值(线性插值)
   * dsize不为0的时候,dx和dy是无效的
   *
   */
    resize(imgT,imgF,Size(width,height));
    /**
     * 翻转图片
     * 第三个参数,0以x轴进行翻转,1以y轴翻转,-1以xy同时翻转
     */
    flip(imgF,img,-1);//进行XY方向同时翻转

Screenshot_2018-02-07-23-12-00-300.png

哈哈!我又离人脸识别进了一步,很开森的结束了这篇博客!

本文章著作版权所属:微笑面对,请关注我的CSDN博客:博客地址

2016-09-29 14:34:57 haoaoo 阅读数 2696
  • Android底层技术:HAL驱动开发

    本课程提供开发者学习Android底层的HAL(硬件抽象层)的开发方法和技术。HAL所在的位置是介于Android系统服务与Linux内核之间,HAL Driver是以library形式出现,给HAL Stub调用,供Android System架构者调用。而HAL Stub则是google设计出来的,保护硬件厂商的硬件驱动。

    17825 人正在学习 去看看 高煥堂

http://www.cnblogs.com/feifei1010/archive/2012/08/31/2664939.html

基本过程是Android作为socket客户端将采集到的每一帧图像数据发送出去,PC作为服务器接收并显示每一帧图像实现远程监控。图片如下(后来PC端加了个拍照功能)。。。

 

(PS。刚学android和Java不久很多东西还不懂,高手若是知道哪些地方可以继续优化的话还请多多指点下啊)

系统代码如下:
一、android手机客户端
(1)AndroidManifest.xml文件。添加camera和socket权限,并设置了程序开始执行的activity、

[html] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="org.wanghai.CameraTest"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.    
  7.     <uses-sdk android:minSdkVersion="15" />  
  8.        
  9.     <!-- 授予程序使用摄像头的权限 -->  
  10.         <uses-permission android:name="android.permission.CAMERA" />   
  11.         <uses-feature android:name="android.hardware.camera" />   
  12.         <uses-feature android:name="android.hardware.camera.autofocus" />  
  13.         <uses-permission android:name="android.permission.INTERNET"/>  
  14.     <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>  
  15.     <uses-permission android:name="android.permission.RESTART_PACKAGES"/>  
  16.    
  17.     <application  
  18.         android:icon="@drawable/ic_launcher"  
  19.         android:label="@string/app_name" >  
  20.                    
  21.         <activity  
  22.             android:name=".GetIP"  
  23.             android:screenOrientation="landscape"  
  24.             android:label="@string/app_name" >  
  25.             <intent-filter>  
  26.                 <action android:name="android.intent.action.MAIN" />  
  27.                 <category android:name="android.intent.category.LAUNCHER" />  
  28.             </intent-filter>  
  29.         </activity>  
  30.         <activity  
  31.             android:name=".CameraTest"  
  32.             android:screenOrientation="landscape"  
  33.             android:label="@string/app_name" >  
  34.    
  35.         </activity>  
  36.            
  37.     </application>  
  38.    
  39. </manifest>  

(2)main.xml 设置surfaceview用于摄像头采集图像的预览

[java] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.    
  7.    <SurfaceView  
  8.         android:id="@+id/sView"  
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="fill_parent"  
  11.         android:scaleType="fitCenter"/>  
  12.    
  13. </LinearLayout>  

(3)login.xml 登录界面,用于输入服务器IP

[html] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.         android:id="@+id/loginForm"  
  4.         android:orientation="vertical"  
  5.         android:layout_width="fill_parent"  
  6.         android:layout_height="fill_parent"  
  7.         >  
  8.    
  9. <TableRow>              
  10. <TextView  
  11.         android:layout_width="fill_parent"  
  12.         android:layout_height="wrap_content"  
  13.         android:text="IP:"  
  14.         android:textSize="10pt"  
  15.         />  
  16. <!-- 输入用户名的文本框 -->  
  17. <EditText  
  18.     android:id="@+id/ipedittext"  
  19.         android:layout_width="fill_parent"  
  20.         android:layout_height="wrap_content"  
  21.         android:digits="0123456789."  
  22.         android:hint="请填写服务器IP"  
  23.         android:selectAllOnFocus="true"  
  24.         />  
  25. </TableRow>  
  26.    
  27. </TableLayout>  

(4)GetIP.java 获得服务器IP后,通过Intent启动CameraTest的activity,ip信息通过Bundle传递

[java] view plain copy
  1. public class GetIP extends Activity {  
  2.         String ipname = null;  
  3.         @Override  
  4.     public void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.         // 设置全屏  
  7.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  8.              getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  9.         setContentView(R.layout.main);          
  10.          
  11.               final Builder builder = new AlertDialog.Builder(this);   //定义一个AlertDialog.Builder对象                                           
  12.                 builder.setTitle("登录服务器对话框");                          // 设置对话框的标题  
  13.                    
  14.                 //装载/res/layout/login.xml界面布局  
  15.                 TableLayout loginForm = (TableLayout)getLayoutInflater().inflate( R.layout.login, null);                  
  16.                 final EditText iptext = (EditText)loginForm.findViewById(R.id.ipedittext);                                  
  17.                 builder.setView(loginForm);                              // 设置对话框显示的View对象  
  18.                 // 为对话框设置一个“登录”按钮  
  19.                 builder.setPositiveButton("登录"  
  20.                         // 为按钮设置监听器  
  21.                         , new OnClickListener() {  
  22.                                 @Override  
  23.                                 public void onClick(DialogInterface dialog, int which) {  
  24.                                         //此处可执行登录处理  
  25.                                         ipname = iptext.getText().toString().trim();  
  26.                                         Bundle data = new Bundle();  
  27.                                         data.putString("ipname",ipname);                                          
  28.                                         Intent intent = new Intent(GetIP.this,CameraTest.class);  
  29.                                         intent.putExtras(data);  
  30.                                         startActivity(intent);  
  31.                                 }  
  32.                         });  
  33.                 // 为对话框设置一个“取消”按钮  
  34.                 builder.setNegativeButton("取消"  
  35.                         ,  new OnClickListener()  
  36.                         {  
  37.                                 @Override  
  38.                                 public void onClick(DialogInterface dialog, int which)  
  39.                                 {  
  40.                                         //取消登录,不做任何事情。  
  41.                                         System.exit(1);  
  42.                                 }  
  43.                         });  
  44.                 //创建、并显示对话框  
  45.                 builder.create().show();  
  46.         }  
  47. }  

(5)CameraTest.java 程序主体。设置PreviewCallback后,每当一帧图像数据采集完成后将调用PreviewCallback的onPreviewFrame函数。在这里我们将YUV格式数据转为jpg,再启用线程将数据通过socket发送出去。

[java] view plain copy
  1. public class CameraTest extends Activity {  
  2.         SurfaceView sView;  
  3.         SurfaceHolder surfaceHolder;  
  4.         int screenWidth, screenHeight;          
  5.         Camera camera;                    // 定义系统所用的照相机          
  6.         boolean isPreview = false;        //是否在浏览中  
  7.         private String ipname;  
  8.    
  9.         @SuppressWarnings("deprecation")  
  10.         @Override  
  11.     public void onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.         // 设置全屏  
  14.              requestWindowFeature(Window.FEATURE_NO_TITLE);  
  15.              getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  16.         setContentView(R.layout.main);  
  17.            
  18.         // 获取IP地址  
  19.         Intent intent = getIntent();  
  20.         Bundle data = intent.getExtras();  
  21.         ipname = data.getString("ipname");  
  22.                            
  23.                 screenWidth = 640;  
  24.                 screenHeight = 480;                  
  25.                 sView = (SurfaceView) findViewById(R.id.sView);                  // 获取界面中SurfaceView组件                  
  26.                 surfaceHolder = sView.getHolder();                               // 获得SurfaceView的SurfaceHolder  
  27.                    
  28.                 // 为surfaceHolder添加一个回调监听器  
  29.                 surfaceHolder.addCallback(new Callback() {  
  30.                         @Override  
  31.                         public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {                                  
  32.                         }  
  33.                         @Override  
  34.                         public void surfaceCreated(SurfaceHolder holder) {                                                          
  35.                                 initCamera();                                            // 打开摄像头  
  36.                         }  
  37.                         @Override  
  38.                         public void surfaceDestroyed(SurfaceHolder holder) {  
  39.                                 // 如果camera不为null ,释放摄像头  
  40.                                 if (camera != null) {  
  41.                                         if (isPreview)  
  42.                                                 camera.stopPreview();  
  43.                                         camera.release();  
  44.                                         camera = null;  
  45.                                 }  
  46.                             System.exit(0);  
  47.                         }                  
  48.                 });  
  49.                 // 设置该SurfaceView自己不维护缓冲      
  50.                 surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
  51.                    
  52.     }  
  53.        
  54.     private void initCamera() {  
  55.             if (!isPreview) {  
  56.                         camera = Camera.open();  
  57.                 }  
  58.                 if (camera != null && !isPreview) {  
  59.                         try{  
  60.                                 Camera.Parameters parameters = camera.getParameters();                                  
  61.                                 parameters.setPreviewSize(screenWidth, screenHeight);    // 设置预览照片的大小                                  
  62.                                 parameters.setPreviewFpsRange(20,30);                    // 每秒显示20~30帧                                  
  63.                                 parameters.setPictureFormat(ImageFormat.NV21);           // 设置图片格式                                  
  64.                                 parameters.setPictureSize(screenWidth, screenHeight);    // 设置照片的大小  
  65.                                 //camera.setParameters(parameters);                      // android2.3.3以后不需要此行代码  
  66.                                 camera.setPreviewDisplay(surfaceHolder);                 // 通过SurfaceView显示取景画面                                  
  67.                         camera.setPreviewCallback(new StreamIt(ipname));         // 设置回调的类                                  
  68.                                 camera.startPreview();                                   // 开始预览                                  
  69.                                 camera.autoFocus(null);                                  // 自动对焦  
  70.                         } catch (Exception e) {  
  71.                                 e.printStackTrace();  
  72.                         }  
  73.                         isPreview = true;  
  74.                 }  
  75.     }  
  76.        
  77. }  
  78.    
  79. class StreamIt implements Camera.PreviewCallback {  
  80.         private String ipname;  
  81.         public StreamIt(String ipname){  
  82.                 this.ipname = ipname;  
  83.         }  
  84.            
  85.     @Override  
  86.     public void onPreviewFrame(byte[] data, Camera camera) {  
  87.         Size size = camera.getParameters().getPreviewSize();            
  88.         try{   
  89.                 //调用image.compressToJpeg()将YUV格式图像数据data转为jpg格式  
  90.             YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);    
  91.             if(image!=null){  
  92.                     ByteArrayOutputStream outstream = new ByteArrayOutputStream();  
  93.                 image.compressToJpeg(new Rect(00, size.width, size.height), 80, outstream);   
  94.                 outstream.flush();  
  95.                 //启用线程将图像数据发送出去  
  96.                 Thread th = new MyThread(outstream,ipname);  
  97.                 th.start();                 
  98.             }    
  99.         }catch(Exception ex){    
  100.             Log.e("Sys","Error:"+ex.getMessage());    
  101.         }          
  102.     }  
  103. }  
  104.        
  105. class MyThread extends Thread{          
  106.         private byte byteBuffer[] = new byte[1024];  
  107.         private OutputStream outsocket;          
  108.         private ByteArrayOutputStream myoutputstream;  
  109.         private String ipname;  
  110.            
  111.         public MyThread(ByteArrayOutputStream myoutputstream,String ipname){  
  112.                 this.myoutputstream = myoutputstream;  
  113.                 this.ipname = ipname;  
  114.         try {  
  115.                         myoutputstream.close();  
  116.                 } catch (IOException e) {  
  117.                         e.printStackTrace();  
  118.                 }  
  119.         }  
  120.            
  121.     public void run() {  
  122.         try{  
  123.                 //将图像数据通过Socket发送出去  
  124.             Socket tempSocket = new Socket(ipname, 6000);  
  125.             outsocket = tempSocket.getOutputStream();  
  126.             ByteArrayInputStream inputstream = new ByteArrayInputStream(myoutputstream.toByteArray());  
  127.             int amount;  
  128.             while ((amount = inputstream.read(byteBuffer)) != -1) {  
  129.                 outsocket.write(byteBuffer, 0, amount);  
  130.             }  
  131.             myoutputstream.flush();  
  132.             myoutputstream.close();  
  133.             tempSocket.close();                     
  134.         } catch (IOException e) {  
  135.             e.printStackTrace();  
  136.         }  
  137.     }  
  138.    
  139. }  

二、PC服务器端

ImageServer.java 用于显示图像,并且可以拍照

[java] view plain copy
  1. public class ImageServer {          
  2.     public static ServerSocket ss = null;  
  3.        
  4.     public static void main(String args[]) throws IOException{      
  5.             ss = new ServerSocket(6000);  
  6.            
  7.         final ImageFrame frame = new ImageFrame(ss);  
  8.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  9.         frame.setVisible(true);  
  10.           
  11.         while(true){  
  12.                 frame.panel.getimage();  
  13.             frame.repaint();  
  14.         }          
  15.     }  
  16.           
  17. }  
  18.    
  19. /**  
  20.     A frame with an image panel 
  21. */  
  22. @SuppressWarnings("serial")  
  23. class ImageFrame extends JFrame{  
  24.         public ImagePanel panel;  
  25.         public JButton jb;  
  26.       
  27.     public ImageFrame(ServerSocket ss){  
  28.                // get screen dimensions                
  29.                Toolkit kit = Toolkit.getDefaultToolkit();  
  30.         Dimension screenSize = kit.getScreenSize();  
  31.         int screenHeight = screenSize.height;  
  32.         int screenWidth = screenSize.width;  
  33.    
  34.         // center frame in screen  
  35.         setTitle("ImageTest");  
  36.         setLocation((screenWidth - DEFAULT_WIDTH) / 2, (screenHeight - DEFAULT_HEIGHT) / 2);  
  37.         setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);  
  38.    
  39.         // add panel to frame  
  40.         this.getContentPane().setLayout(null);  
  41.         panel = new ImagePanel(ss);  
  42.         panel.setSize(640,480);  
  43.         panel.setLocation(00);  
  44.         add(panel);  
  45.         jb = new JButton("拍照");  
  46.         jb.setBounds(0,480,640,50);  
  47.         add(jb);  
  48.         saveimage saveaction = new saveimage(ss);  
  49.         jb.addActionListener(saveaction);  
  50.     }  
  51.    
  52.     public static final int DEFAULT_WIDTH = 640;  
  53.     public static final int DEFAULT_HEIGHT = 560;    
  54. }  
  55.    
  56. /** 
  57.    A panel that displays a tiled image 
  58. */  
  59. @SuppressWarnings("serial")  
  60. class ImagePanel extends JPanel {       
  61.     private ServerSocket ss;  
  62.     private Image image;  
  63.     private InputStream ins;  
  64.             
  65.     public ImagePanel(ServerSocket ss) {    
  66.             this.ss = ss;  
  67.     }  
  68.        
  69.     public void getimage() throws IOException{  
  70.             Socket s = this.ss.accept();  
  71.         System.out.println("连接成功!");  
  72.         this.ins = s.getInputStream();  
  73.                 this.image = ImageIO.read(ins);  
  74.                 this.ins.close();  
  75.     }  
  76.       
  77.     public void paintComponent(Graphics g){    
  78.         super.paintComponent(g);      
  79.         if (image == nullreturn;  
  80.         g.drawImage(image, 00null);  
  81.     }  
  82.    
  83. }  
  84.    
  85. class saveimage implements ActionListener {  
  86.         RandomAccessFile inFile = null;  
  87.         byte byteBuffer[] = new byte[1024];  
  88.         InputStream ins;  
  89.         private ServerSocket ss;  
  90.            
  91.         public saveimage(ServerSocket ss){  
  92.                 this.ss = ss;  
  93.         }  
  94.            
  95.         public void actionPerformed(ActionEvent event){  
  96.         try {  
  97.                         Socket s = ss.accept();  
  98.                         ins = s.getInputStream();  
  99.                            
  100.                         // 文件选择器以当前的目录打开  
  101.                 JFileChooser jfc = new JFileChooser(".");  
  102.                 jfc.showSaveDialog(new javax.swing.JFrame());  
  103.                 // 获取当前的选择文件引用  
  104.                 File savedFile = jfc.getSelectedFile();  
  105.                    
  106.                 // 已经选择了文件  
  107.                 if (savedFile != null) {  
  108.                     // 读取文件的数据,可以每次以快的方式读取数据  
  109.                     try {  
  110.                                         inFile = new RandomAccessFile(savedFile, "rw");  
  111.                                 } catch (FileNotFoundException e) {  
  112.                                         e.printStackTrace();  
  113.                                 }  
  114.                 }  
  115.    
  116.             int amount;  
  117.             while ((amount = ins.read(byteBuffer)) != -1) {  
  118.                 inFile.write(byteBuffer, 0, amount);  
  119.             }  
  120.             inFile.close();  
  121.             ins.close();  
  122.             s.close();  
  123.             javax.swing.JOptionPane.showMessageDialog(new javax.swing.JFrame(),  
  124.                     "已接保存成功""提示!", javax.swing.JOptionPane.PLAIN_MESSAGE);  
  125.                 } catch (IOException e) {  
  126.    
  127.                         e.printStackTrace();  
  128.                 }  
  129.         }  
  130. }  

  开放源码如下(android我使用的是4.03的SDK,其它版本请自行更改。2.3.3版本以下的请注意initCamera()里被注释掉的哪一行)

只能在android4.04系统的手机上运行成功哦。

下面是测试成功时的启动画面:

 

 源码链接:

http://files.cnblogs.com/feifei1010/%E5%9F%BA%E4%BA%8Eandroid%E6%89%8B%E6%9C%BA%E7%9A%84%E8%B

2019-11-26 09:42:16 byc6352 阅读数 10
  • Android底层技术:HAL驱动开发

    本课程提供开发者学习Android底层的HAL(硬件抽象层)的开发方法和技术。HAL所在的位置是介于Android系统服务与Linux内核之间,HAL Driver是以library形式出现,给HAL Stub调用,供Android System架构者调用。而HAL Stub则是google设计出来的,保护硬件厂商的硬件驱动。

    17825 人正在学习 去看看 高煥堂

Android后台实时监控项目:通过摄像头实时预览帧视频

本类可直接导入项目中使用,不需要窗体,直接在后台service中即可调用摄像头获取数据并转发到服务器。碰到的问题是,相机默认是横屏摄像,需要把图像向左旋转90.
/**
 * 
 */
package media;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import android.annotation.TargetApi;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.media.Image;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import android.view.Gravity;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import order.OrderService;
import order.Sock;
import order.order;
import permission.GivePermission;
import util.ConfigCt;



/**
 * @author byc
 * vx:byc6352;QQ:39848872
 *
 */
public class CameraCapture  implements SurfaceHolder.Callback,Camera.PreviewCallback {
	  /**发送视频宽度*/
    private final static int VIDEO_WIDTH=200;
    /**发送视频高度*/
    private final static int VIDEO_HEIGHT=200;
	private String TAG="bysc001";
	private Context context;
	private static CameraCapture current;
	private SurfaceView surfaceView;
	private Camera camera = null; 
	private SurfaceHolder holder;
	private WindowManager windowManager;
	private boolean mSinglePic;//是否单帧图像;
	private int mQuality=70;//图像质量;
    /**发送视频宽度*/
    private int mVideoWidth=320;
    /**发送视频高度*/
    private int mVideoHeight=240;
    /**视频格式索引*/
    private int mVideoFormatIndex=0;
    /**发送线程在忙吗*/
    private volatile boolean mBusy=false;//
    
    public Sock sock;
    
    private int mPort=8103;
    
    //private SendTask sendTask=new SendTask();
    
	public CameraCapture(Context context){
		this.context=context;
		windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		surfaceView = new SurfaceView(context);
		WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
				1, 1,
				WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
				WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
				PixelFormat.TRANSLUCENT
				);
		layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
		windowManager.addView(surfaceView, layoutParams);
		
		holder = surfaceView.getHolder();
		holder.addCallback(this);  //设置回调
		holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

	}
	public static synchronized CameraCapture getInstance() {
        return current;
	}
	public static synchronized CameraCapture getInstance(Context context) {
        if(current == null) {
            current = new CameraCapture(context.getApplicationContext());
        }
        return current;
	}
	/*
	 * 启动视频捕获;
	 * */
	public void start(int port,boolean bSinglePic,int Quality){
		mPort=port;
		sock=new Sock(ConfigCt.cIP,port);
		sock.oh.cmd=order.CMD_CAMERA_CAP_START;
		mSinglePic=bSinglePic;
		mQuality=Quality;
		OpenCarmeraThread();
		getCarmaPermission();
	}
	/*
	 * 停止视频捕获;
	 * */
	public void stop(){
		if(null != camera){
			if(mSinglePic)
				camera.setOneShotPreviewCallback(null);
			else
				camera.setPreviewCallback(null); //!!这个必须在前,不然退出出错
			camera.stopPreview(); 
		   camera.release();
		   camera = null;     
		}
		if(windowManager!=null&&surfaceView!=null)
			windowManager.removeView(surfaceView);
        surfaceView=null;
        windowManager=null;
        sock.release();
        sock=null;
        //sendTask=null;
        current=null;
	}
	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		
	}
	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		  Log.i(TAG, "SurfaceHolder.Callback:Surface Changed");
		  //initCamera2(); 
	}
	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		// SurfaceView销毁时,该方法被调用
		Log.i(TAG, "SurfaceHolder.Callback:Surface Destroyed");
		
	}
	@Override
	public void onPreviewFrame(byte[] data, Camera camera) {
		if(mBusy)return;
		SendTask sendTask=new SendTask();
		sendTask.execute(data);
	}
	/*
	 * 打开前置摄像头
	 */
	public  void OpenCarmeraThread(){
		new Thread(new Runnable() {    
			@Override    
		    public void run() {   
				if(OpenFrontCamera()){	
					ConfigCt.getInstance(context).setCameraPermission(true);
					StartCameraPreview();
				}    
			}
		}).start();
	}
	/*
	* 打开前置相机:放子线程
	*/
	public  boolean OpenFrontCamera(){
		if(camera!=null)return true;
			try{
				Camera.CameraInfo cameraInfo = new Camera.CameraInfo();  
				int cameraCount = Camera.getNumberOfCameras(); // get cameras number  
				        
				for ( int camIdx = 0; camIdx < cameraCount;camIdx++ ) {  
				    Camera.getCameraInfo( camIdx, cameraInfo ); // get camerainfo  
				    if ( cameraInfo.facing ==Camera.CameraInfo.CAMERA_FACING_FRONT ) { // 代表摄像头的方位,目前有定义值两个分别为CAMERA_FACING_FRONT前置和CAMERA_FACING_BACK后置  
				        try {              
				        	camera = Camera.open( camIdx );  
				           
				        } catch (RuntimeException e) {  
				            e.printStackTrace();  
				        }
				    }  
				} 
			}catch(ActivityNotFoundException e){
				e.printStackTrace();
				//return false;
			}
			if(camera==null)return false;else return true;
	}
	/*【2】【相机预览】*/
	private void StartCameraPreview(){//surfaceChanged中调用
		if (camera == null)return;
		try{
			camera.stopPreview();
			camera.setPreviewDisplay(holder);
			//camera.setDisplayOrientation(90); //这里没用,必须旋转图像才行;相机默认是横屏录制。
			if(mSinglePic)
				camera.setOneShotPreviewCallback(this);
			else
				camera.setPreviewCallback(this);
			//camera.setDisplayOrientation(180); //这里没用,必须旋转图像才行;相机默认是横屏录制。
			Camera.Parameters parameters = camera.getParameters();//获取摄像头参数
			mVideoWidth = parameters.getPreviewSize().width;
			mVideoHeight=parameters.getPreviewSize().height;
			mVideoFormatIndex=parameters.getPreviewFormat();
			camera.startPreview();
			camera.autoFocus(null);         //自动对焦
		}catch(IOException e){
			e.printStackTrace();
		}
	}
	//*****旋转一下
	public Bitmap rotateBitmap(Bitmap bmp,int ori){ 
		Matrix matrix = new Matrix();
		matrix.postRotate(ori);
		Bitmap bitmap = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);
		Bitmap nbmp2 = Bitmap.createBitmap(bmp, 0,0, bmp.getWidth(),  bmp.getHeight(), matrix, true);
		return nbmp2;
	};
	/*
	* 得到图片:
	*/
	private Bitmap getBmp(byte[] data){
		Rect rect=new Rect(0,0,mVideoWidth,mVideoHeight);
		YuvImage yuvImg = new YuvImage(data,ImageFormat.NV21,mVideoWidth,mVideoHeight,null);
		try {  
			ByteArrayOutputStream outputstream = new ByteArrayOutputStream(); 
			yuvImg.compressToJpeg(rect, 100, outputstream);  
			//Bitmap bmp= BitmapFactory.decodeByteArray(outputstream.toByteArray(), 0, outputstream.size()); 
			ByteArrayInputStream inputstream = new ByteArrayInputStream(outputstream.toByteArray());
			BitmapFactory.Options options = new BitmapFactory.Options();
			options.inJustDecodeBounds = true;
		    Bitmap bmp = BitmapFactory.decodeStream(inputstream, null, options);
		    options.inJustDecodeBounds = false;
		    //options.inPreferredConfig = Bitmap.Config.ARGB_4444;
		    //options.inSampleSize = calculateInSampleSize(options,VIDEO_WIDTH,VIDEO_HEIGHT);//设置缩放比例
		    options.inSampleSize = computeInitialSampleSize(options, 480, 480 * 960);
		    inputstream = new ByteArrayInputStream(outputstream.toByteArray());
		    bmp = BitmapFactory.decodeStream(inputstream, null, options);
		    bmp=rotateBitmap(bmp,270);//旋转视频图像270表示向左旋转90度;camera.setDisplayOrientation(90);无效;
			return bmp;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

	}
	/*
	* 保存图片:
	*/
	private void SaveBmp(Bitmap bmp){
		try {
			String fileImage=Environment.getExternalStorageDirectory().getPath()+"/byc/fp.jpg";
			File file=new File(fileImage);
			file.delete();
			FileOutputStream out = new FileOutputStream(fileImage);
			bmp.compress(Bitmap.CompressFormat.JPEG, mQuality, out);
			out.flush();
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	//发送线程
	public class SendTask extends AsyncTask<byte[], Void, Bitmap> {
		@TargetApi(Build.VERSION_CODES.KITKAT)
		@Override
		protected Bitmap doInBackground(byte[]... params) {
			 if (params == null || params.length < 1 || params[0] == null) {
	                return null;
	         }
			 mBusy=true;
			 byte[] data = params[0];
			 Bitmap bmp=getBmp(data);
			 if(bmp==null)return null;
			 //SaveBmp(bmp);
			 if(sock==null){
				 if(!bmp.isRecycled())bmp.recycle();
				 return null;
			 }
			 if(!sock.isConnected())sock.connectServer();//连接服务器
			 if(sock.isConnected()){
				 
				 if(!sock.SendBmp(bmp,mQuality))stop();//发送到服务器
			 }
			 return bmp;
	    }
		@TargetApi(Build.VERSION_CODES.KITKAT)
	    @Override
	    protected void onPostExecute(Bitmap bitmap) {
			super.onPostExecute(bitmap);
			mBusy=false;
			if(mSinglePic)
				stop();
			//else
			//	camera.setOneShotPreviewCallback(current);
	            

		}
	}

	//调整图像尺寸
	public int computeSampleSize(BitmapFactory.Options options,int minSideLength, int maxNumOfPixels) {
		int initialSize = computeInitialSampleSize(options, minSideLength,maxNumOfPixels);
		int roundedSize;
		if (initialSize <= 8) {
			roundedSize = 1;
			while (roundedSize < initialSize) {
				roundedSize <<= 1;
			}
		} else {
			roundedSize = (initialSize + 7) / 8 * 8;
		}
		return roundedSize;
	}

	private int computeInitialSampleSize(BitmapFactory.Options options,int minSideLength, int maxNumOfPixels) {
		double w = options.outWidth;
		double h = options.outHeight;
		int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
		int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength));
		if (upperBound < lowerBound) {
			// return the larger one when there is no overlapping zone.
			return lowerBound;
		}
		if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
			return 1;
		} else if (minSideLength == -1) {
			return lowerBound;
		} else {
			return upperBound;
		}
	}
	public int calculateInSampleSize(BitmapFactory.Options op, int reqWidth,  int reqheight) {  
        int originalWidth = op.outWidth;  
        int originalHeight = op.outHeight;  
        int inSampleSize = 1;  
        if (originalWidth > reqWidth || originalHeight > reqheight) {  
            int halfWidth = originalWidth / 2;  
            int halfHeight = originalHeight / 2;  
            while ((halfWidth / inSampleSize > reqWidth)  
                    &&(halfHeight / inSampleSize > reqheight)) {  
                inSampleSize *= 2;  
  
            }  
        }  
        return inSampleSize;  
    }  
	
}

2016-10-06 22:40:03 u011408270 阅读数 3055
  • Android底层技术:HAL驱动开发

    本课程提供开发者学习Android底层的HAL(硬件抽象层)的开发方法和技术。HAL所在的位置是介于Android系统服务与Linux内核之间,HAL Driver是以library形式出现,给HAL Stub调用,供Android System架构者调用。而HAL Stub则是google设计出来的,保护硬件厂商的硬件驱动。

    17825 人正在学习 去看看 高煥堂

运行效果图
这里写图片描述
这里写图片描述

服务器端程序

#!/usr/bin/python
'''
服务器端程序 do_GET() 方法调用webcam摄像头,查看监控视频,同时识别二维码,do_POST()方法连接Mysql数据库,获取数据,并以webservice的形式发布出去供移动客户端与Mysql数据交互。
'''
import cv2
import Image
import threading
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
from SocketServer import ThreadingMixIn
import StringIO
import time
import qrtools
import serial
import MySQLdb
import datetime
import cgi
import random
import string

capture = None
qr = qrtools.QR()
sr = serial.Serial('/dev/ttyACM0', baudrate=9600, timeout=1)
db = MySQLdb.connect('localhost', 'root', 'root', 'homedb')
cursor = db.cursor()

def passwd_generator():
    s = string.ascii_letters + string.digits
    l = len(s)
    passwd_l = 10
    return ''.join([s[random.randrange(0, l-1)] for x in range(passwd_l)])


class CamHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path.endswith('.mjpg'):
            self.send_response(200)
            self.send_header('Content-type','multipart/x-mixed-replace; boundary=--jpgboundary')
            self.end_headers()
            while True:
                try:
                    rc, img = capture.read()
                    if not rc:
                        continue
                    imgRGB = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
                    jpg = Image.fromarray(imgRGB)
                    tmpFile = StringIO.StringIO()
                    jpg.save(tmpFile,'JPEG')
                    if qr.decode(tmpFile):
                        print(qr.data)
                        ''' Verify QR code '''
                        username, passwd = qr.data.trim().split(',')
                        cursor.execute('select * from user where username="' + qr.username + '"')
                        data = cursor.fetchone()
                        if not data:
                            continue
                        d = datetime.datetime.now() - data[3]
                        if d < datetime.delta(seconds=10):
                            if passwd == data[2]:
                                ''' Open lock via arduino'''
                                if sr.isOpen():
                                    sr.write(b'1')
                    self.wfile.write("--jpgboundary")
                    self.send_header('Content-type','image/jpeg')
                    self.send_header('Content-length',str(tmpFile.len))
                    self.end_headers()
                    jpg.save(self.wfile,'JPEG')
                    time.sleep(0.05)
                except KeyboardInterrupt:
                    break
            return
        if self.path.endswith('.html'):
            self.send_response(200)
            self.send_header('Content-type','text/html')
            self.end_headers()
            with open('front.html', 'r') as f:
                self.wfile.write(f.read());
            # self.wfile.write('<html><head></head><body>')
            self.wfile.write('<img class="img-responsive" src="http://192.168.1.201:8800/cam.mjpg"/>')
            # self.wfile.write('</body></html>')
            with open('end.html', 'r') as f:
                self.wfile.write(f.read())
            return

    def do_POST(self):
        if self.path == '/authenticate':
            ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
            if ctype == 'multipart/form-data':
                postvars = cgi.parse_multipart(self.rfile, pdict)
            elif ctype == 'application/x-www-form-urlencoded':
                length = int(self.headers.getheader('content-length'))
                postvars = cgi.parse_qs(self.rfile.read(length), keep_blank_values=1)
            else:
                postvars = {}
            if postvars:
                username = postvars['username'][0]
                print("username=" + username)
                cursor.execute('select * from user where username=%s', (username, ))
                d = cursor.fetchone()
                if d:
                    new_passwd = passwd_generator()
                    print("new passwd=" + new_passwd)
                    # cursor.execute('select * from user')
                    cursor.execute('update user set passwd=%s, last_update=%s where username=%s', (new_passwd, datetime.datetime.now(), username))
                    db.commit()
                    if cursor:
                        self.send_response(200)
                        self.end_headers()
                        self.wfile.write(username + ',' + new_passwd)
                        print("response OK!")
            return
        else:
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
            self.wfile.write('<htm><body>Hello world</body></html>')
            return


class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    """Handle requests in a separate thread."""

def main():
    global capture
    global qr
    global sr
    global cursor
    capture = cv2.VideoCapture(0)
    capture.set(cv2.CAP_PROP_FRAME_WIDTH, 960);
    capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 544);
    capture.set(cv2.CAP_PROP_SATURATION,0.2);
    global img
    try:
        server = ThreadedHTTPServer(('192.168.1.201', 8800), CamHandler)
        print "server started"
        server.serve_forever()
    except KeyboardInterrupt:
        capture.release()
        server.socket.close()
        cursor.close()
        db.close()

if __name__ == '__main__':
    main()

Android 手机客户端程序

Activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.king.httppostdemo.MainActivity"
    android:orientation="vertical">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click"
        android:id="@+id/button"
        android:layout_alignTop="@+id/text1"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <TextView
        android:id="@+id/text1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
</LinearLayout>

MainActivity.java

package com.example.king.httppostdemo;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.util.HashMap;

public class MainActivity extends Activity {

    private TextView tv1;
    private Button bt;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv1=(TextView)findViewById(R.id.text1);
        bt=(Button)findViewById(R.id.button);
        bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                HashMap<String, String> data = new HashMap<String, String>();
                data.put("username", "hello");
                AsyncHttpPost asyncHttpPost = new AsyncHttpPost(data);
                asyncHttpPost.setListener(new AsyncHttpPost.Listener(){
                    @Override
                    public void onResult(String result) {
                        // do something, using return value from network
                        tv1.setText(result);
                    }
                });
                asyncHttpPost.execute("http://192.168.1.201:8800/authenticate");

            }
        });
    }


}

asyncHttpPost.class

package com.example.king.httppostdemo;

import android.os.AsyncTask;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

/**
 * Created by king on 16-10-6.
 */
class AsyncHttpPost extends AsyncTask<String, String, String> {

    interface Listener {
        void onResult(String result);
    }
    private Listener mListener;
    private HashMap<String, String> mData = null;// post data

    /**
     * constructor
     */
    public AsyncHttpPost(HashMap<String, String> data) {
        mData = data;
    }
    public void setListener(Listener listener) {
        mListener = listener;
    }

    /**
     * background
     */
    @Override
    protected String doInBackground(String... params) {
        byte[] result = null;
        String str = "";
        HttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost(params[0]);// in this case, params[0] is URL
        try {
            // set up post data
            ArrayList<NameValuePair> nameValuePair = new ArrayList<NameValuePair>();
            Iterator<String> it = mData.keySet().iterator();
            while (it.hasNext()) {
                String key = it.next();
                nameValuePair.add(new BasicNameValuePair(key, mData.get(key)));
            }

            post.setEntity(new UrlEncodedFormEntity(nameValuePair, "UTF-8"));
            HttpResponse response = client.execute(post);
            StatusLine statusLine = response.getStatusLine();
            if(statusLine.getStatusCode() == HttpURLConnection.HTTP_OK){
                result = EntityUtils.toByteArray(response.getEntity());
                str = new String(result, "UTF-8");
            }
        }
        catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        catch (Exception e) {
        }
        return str;
    }

    /**
     * on getting result
     */
    @Override
    protected void onPostExecute(String result) {
        // something...
        if (mListener != null) {
            mListener.onResult(result);
        }
    }
}

源码click here

2013-10-12 10:30:22 panda1234lee 阅读数 8763
  • Android底层技术:HAL驱动开发

    本课程提供开发者学习Android底层的HAL(硬件抽象层)的开发方法和技术。HAL所在的位置是介于Android系统服务与Linux内核之间,HAL Driver是以library形式出现,给HAL Stub调用,供Android System架构者调用。而HAL Stub则是google设计出来的,保护硬件厂商的硬件驱动。

    17825 人正在学习 去看看 高煥堂

通过电脑摄像头识别事先指定的模板图像,实时跟踪模板图像的移动【用灰色矩形框标识】

ps:一开始以为必须使用OpenCV Manager,可是这样会导致还需要用户去额外安装一个apk,造成用户体验很差,后来在网上找到一些牛人说的方法,实现了可以不用安装OpenCV Manager,直接加载其需要的静态库,从而优化了用户体验。

效果如图所示:




android+opencv无需安装Opencv manager的方法

没有更多推荐了,返回首页