Android 举例说明自己的定义Camera图片和预览,以及前后摄像头切换
如何调用本地图片,并调用系统拍摄的图像上一博文解释(http://blog.csdn.net/a123demi/article/details/40003695)的功能。
而本博文将通过实例实现自己定义Camera的功效。详细功能例如以下:
1.实现自己定义Camera拍照;
2.实现前后置摄像头的切换。
3.实现Camera拍照后图片缩小显示以及正常预览;
4.实现Camera拍照后图片保存;
在详细实现代码之前,我们先来了解一下Android api对实现自己定义Camera的介绍。
依据api的介绍,对于Camera应用能够简单总结下面几个步骤。
1.检查Camera是否存在。并在AndroidManifest.xml中赋予相关的权限。
2.创建一个继承于SurfaceView并实现SurfaceHolder接口的Camera Preview类。
3.在2的基础上新建一个Camera Preview布局文件。
4.设置一个拍照的监听事件,比如单击button事件等;
5.实现拍照,并保存拍照后的图片到设备;
6.释放Camera,以方便其它应用能够使用。
以下将通过详细代码实现我们给出的三个功能。
一.相关的xml文件
1.AndroidManifest.xml相关配置以及相关权限,实现步骤一其中的权限配置
<?xml version="1.0" encoding="utf-8"? >
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.camerasurfacedemo"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="19" /> <uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-feature android:name="android.hardware.camera" /> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.camerasurfacedemo.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity> <activity android:name="com.example.camerasurfacedemo.CameraActivity"
></activity>
<activity android:name="com.example.camerasurfacedemo.PreviewActivity"
></activity>
</application> </manifest>
2.activity_main.xml主函数入口。进入自己定义Camera界面入口,实现拍照后图片缩小显示功能
<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:gravity="center_horizontal"
android:orientation="vertical" >
" <Button
android:id="@+id/id_go_camera_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="进入拍照界面" /> <ImageView
android:id="@+id/id_show_camera_iv"
android:layout_width="150dp"
android:layout_height="200dp"
android:gravity="center" /> <TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="拍照图片显示区域"
android:textColor="#FF0000"
android:textSize="20sp" /> </LinearLayout>
3.activity_camera.xml自己定义Camera preview布局,实现步骤2,该界面实现前后置摄像头切换以及自己定义拍照等
<RelativeLayout 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"
>
<LinearLayout
android:id="@+id/id_process_btns_ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentTop="true"
>
<Button
android:id="@+id/id_switch_camera_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="切换前后摄像头"
/>
<Button
android:id="@+id/id_capture_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="拍照"
/>
</LinearLayout>
<SurfaceView
android:id="@+id/id_area_sv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/id_process_btns_ll"
android:text="拍照区域" /> </RelativeLayout>
4.activity_preview.xml实现拍照后图片放大预览
<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:background="#000000"
android:orientation="vertical" > <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="拍照图片预览"
android:textColor="#FF0000"
android:textSize="20sp"
/> <ImageView
android:id="@+id/id_preview_camera_iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center" /> </LinearLayout>
二.java代码实现
1.帮助类HelpUtil.java
package com.example.camerasurfacedemo; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date; import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.net.Uri; public class HelpUtil {
/**
* 依据图片路径获取本地图片的Bitmap
*
* @param url
* @return
*/
public static Bitmap getBitmapByUrl(String url) {
FileInputStream fis = null;
Bitmap bitmap = null;
try {
fis = new FileInputStream(url);
bitmap = BitmapFactory.decodeStream(fis); } catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
bitmap = null;
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
fis = null;
}
} return bitmap;
} /**
* bitmap旋转90度
*
* @param bitmap
* @return
*/
public static Bitmap createRotateBitmap(Bitmap bitmap) {
if (bitmap != null) {
Matrix m = new Matrix();
try {
m.setRotate(90, bitmap.getWidth() / 2, bitmap.getHeight() / 2);// 90就是我们须要选择的90度
Bitmap bmp2 = Bitmap.createBitmap(bitmap, 0, 0,
bitmap.getWidth(), bitmap.getHeight(), m, true);
bitmap.recycle();
bitmap = bmp2;
} catch (Exception ex) {
System.out.print("创建图片失败。" + ex);
}
}
return bitmap;
} public static Bitmap getBitmapByUri(Uri uri,ContentResolver cr){
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeStream(cr
.openInputStream(uri));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
bitmap = null;
}
return bitmap;
} /**
* 获取格式化日期字符串
* @param date
* @return
*/
@SuppressLint("SimpleDateFormat")
public static String getDateFormatString(Date date) {
if (date == null)
date = new Date();
String formatStr = new String();
SimpleDateFormat matter = new SimpleDateFormat("yyyyMMdd_HHmmss");
formatStr = matter.format(date);
return formatStr;
}
}
2.主函数类MainActivity.java
package com.example.camerasurfacedemo; import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView; public class MainActivity extends Activity { private Button goCameraBtn;
private ImageView showCameraIv;
private static final int CAMERA_CODE = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); goCameraBtn = (Button)this.findViewById(R.id.id_go_camera_btn);
goCameraBtn.setOnClickListener(new OnClickListener(){ @Override
public void onClick(View v) {
processGoCamera();
} }); showCameraIv = (ImageView)this.findViewById(R.id.id_show_camera_iv);
showCameraIv.setOnClickListener(new OnClickListener(){ @Override
public void onClick(View v) {
processShowCamera(v);
} });
} /**
* 处理进入camera事件
*/
private void processGoCamera(){
Intent intent = new Intent();
intent.setClass(this, CameraActivity.class);
startActivityForResult(intent,CAMERA_CODE);
} /**
* 处理图片跳转进入预览界面
*/
private void processShowCamera(View v){
Intent intent = new Intent();
intent.setClass(this, PreviewActivity.class);
/**
* 将图片url传给PreviewActivity
*/
intent.putExtra("cameraUrl", v.getContentDescription().toString());
startActivity(intent);
} @Override
public void onActivityResult(int requestCode,int resultCode,Intent data){
super.onActivityResult(requestCode, resultCode, data); if(RESULT_OK == resultCode){
if(CAMERA_CODE == requestCode){
/**
* 获取activity返回的url
*/
Uri uri = data.getData();
String url = uri.toString().substring(uri.toString().indexOf("///")+2);
if(url != null && !TextUtils.isEmpty(url)){
showCameraIv.setContentDescription(url);
showCameraIv.setImageBitmap(HelpUtil.getBitmapByUrl(url));
}
}
} } }
注意:这里通过startActivityForResult(intent,CAMERA_CODE)跳转和 onActivityResult(int requestCode,int resultCode,Intent data)返回拍照后的图片路径信息
3.自己定义Camera preview类CameraActivity.java
package com.example.camerasurfacedemo; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date; import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button; public class CameraActivity extends Activity implements OnClickListener,
SurfaceHolder.Callback { private static final String TAG = CameraActivity.class.getSimpleName();
private static final int MEDIA_TYPE_IMAGE = 1;
private Button switchCameraBtn, captureBtn;
private SurfaceView surfaceSv; private SurfaceHolder mHolder;
private Camera mCamera;
// 0表示后置,1表示前置
private int cameraPosition = 1; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 不显示标题
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_camera); findById();
initData();
} /**
* 初始化view
*/
private void findById() {
switchCameraBtn = (Button) this.findViewById(R.id.id_switch_camera_btn);
captureBtn = (Button) this.findViewById(R.id.id_capture_btn);
surfaceSv = (SurfaceView) this.findViewById(R.id.id_area_sv); switchCameraBtn.setOnClickListener(this);
captureBtn.setOnClickListener(this);
} /**
* 初始化相关data
*/
private void initData() {
// 获得句柄
mHolder = surfaceSv.getHolder();
// 加入回调
mHolder.addCallback(this);
} @Override
public void onStart() {
super.onStart();
if (this.checkCameraHardware(this) && (mCamera == null)) {
// 打开camera
mCamera = getCamera();
if (mHolder != null) {
setStartPreview(mCamera,mHolder);
}
}
} private Camera getCamera() {
Camera camera = null;
try {
camera = Camera.open();
} catch (Exception e) {
// Camera is not available (in use or does not exist)
camera = null;
Log.e(TAG, "Camera is not available (in use or does not exist)");
}
return camera;
} @Override
public void onPause() {
super.onPause();
/**
* 记得释放camera。方便其它应用调用
*/
releaseCamera();
} @Override
public void onDestroy() {
super.onDestroy();
} /**
* 释放mCamera
*/
private void releaseCamera() {
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();// 停掉原来摄像头的预览
mCamera.release();
mCamera = null;
}
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.id_switch_camera_btn:
// 切换前后摄像头
int cameraCount = 0;
CameraInfo cameraInfo = new CameraInfo();
cameraCount = Camera.getNumberOfCameras();// 得到摄像头的个数 for (int i = 0; i < cameraCount; i++) {
Camera.getCameraInfo(i, cameraInfo);// 得到每个摄像头的信息
if (cameraPosition == 1) {
// 如今是后置,变更为前置
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
/**
* 记得释放camera。方便其它应用调用
*/
releaseCamera();
// 打开当前选中的摄像头
mCamera = Camera.open(i);
// 通过surfaceview显示取景画面
setStartPreview(mCamera,mHolder);
cameraPosition = 0;
break;
}
} else {
// 如今是前置。 变更为后置
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
/**
* 记得释放camera,方便其它应用调用
*/
releaseCamera();
mCamera = Camera.open(i);
setStartPreview(mCamera,mHolder);
cameraPosition = 1;
break;
}
} }
break;
case R.id.id_capture_btn:
// 拍照,设置相关參数
Camera.Parameters params = mCamera.getParameters();
params.setPictureFormat(ImageFormat.JPEG);
params.setPreviewSize(800, 400);
// 自己主动对焦
params.setFocusMode(Parameters.FOCUS_MODE_AUTO);
mCamera.setParameters(params);
mCamera.takePicture(null, null, picture);
break;
}
} @Override
public void surfaceCreated(SurfaceHolder holder) { setStartPreview(mCamera,mHolder);
} @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// 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
setStartPreview(mCamera,mHolder);
} @Override
public void surfaceDestroyed(SurfaceHolder holder) {
// 当surfaceview关闭时,关闭预览并释放资源
/**
* 记得释放camera,方便其它应用调用
*/
releaseCamera();
holder = null;
surfaceSv = null;
} /**
* 创建png图片回调数据对象
*/
PictureCallback picture = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null) {
Log.d(TAG,
"Error creating media file, check storage permissions: ");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
returnResult(pictureFile);
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
}; /**
* Create a File for saving an image or video
*/
private static File getOutputMediaFile(int type) {
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this. File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"MyCameraApp");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled. // Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("MyCameraApp", "failed to create directory");
return null;
}
} // Create a media file name
String timeStamp = HelpUtil.getDateFormatString(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + timeStamp + ".png");
} else {
return null;
}
return mediaFile;
} /** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA)) {
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
} /**
* activity返回式返回拍照图片路径
* @param mediaFile
*/
private void returnResult(File mediaFile) {
Intent intent = new Intent();
intent.setData(Uri.fromFile(mediaFile));
this.setResult(RESULT_OK, intent);
this.finish();
} /**
* 设置camera显示取景画面,并预览
* @param camera
*/
private void setStartPreview(Camera camera,SurfaceHolder holder){
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
注意:
1.检查Camera是否存在
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA)) {
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
2.创建png格式的回调接口
/**
* 创建png图片回调数据对象
*/
PictureCallback picture = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null) {
Log.d(TAG,
"Error creating media file, check storage permissions: ");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
returnResult(pictureFile);
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
};
3.生成图片文件并保存
/**
* Create a File for saving an image or video
*/
private static File getOutputMediaFile(int type) {
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this. File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"MyCameraApp");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled. // Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("MyCameraApp", "failed to create directory");
return null;
}
} // Create a media file name
String timeStamp = HelpUtil.getDateFormatString(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + timeStamp + ".png");
} else {
return null;
}
return mediaFile;
}
4.Camera一定要release
/**
* 释放mCamera
*/
private void releaseCamera() {
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();// 停掉原来摄像头的预览
mCamera.release();
mCamera = null;
}
}
5.Activity结果返回
/**
* activity返回式返回拍照图片路径
* @param mediaFile
*/
private void returnResult(File mediaFile) {
Intent intent = new Intent();
intent.setData(Uri.fromFile(mediaFile));
this.setResult(RESULT_OK, intent);
this.finish();
}
4.图片正常预览PreviewActivity.java
package com.example.camerasurfacedemo; import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Window;
import android.widget.ImageView;
import android.widget.Toast; public class PreviewActivity extends Activity { private ImageView previewCameraIv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_preview); previewCameraIv = (ImageView)this.findViewById(R.id.id_preview_camera_iv); Intent intent = this.getIntent();
String cameraUrl = intent.getStringExtra("cameraUrl").toString();
if(cameraUrl != null && !TextUtils.isEmpty(cameraUrl)){
previewCameraIv.setImageBitmap(HelpUtil.getBitmapByUrl(cameraUrl));
}else{
Toast.makeText(this, "图片路径错误", Toast.LENGTH_SHORT).show();
}
} }
以上就是本博文的全部内容。谢谢品读。
源代码路径:http://download.csdn.net/detail/a123demi/8029265
版权声明:本文博主原创文章,博客,未经同意不得转载。
Android 举例说明自己的定义Camera图片和预览,以及前后摄像头切换的更多相关文章
- 我的Android进阶之旅------>Android疯狂连连看游戏的实现之游戏效果预览(一)
今天看完了李刚老师的<疯狂Android讲义>一书中的第18章<疯狂连连看>,从而学会了如何编写一个简单的Android疯狂连连看游戏. 开发这个流行的小游戏,难度适中,而且能 ...
- jQuery Lightbox图片放大预览
简介:jQuery Lightbox图片放大预览代码是一款可以在用户点击页面中的小图片时,将该图片的高清版本以Lightbox的方式放大显示在页面的中间,提高用户的体验度. 效果展示 http://h ...
- js实现FileUpload选择图片后预览功能
当asp.net的FileUpload选择一个图片后不需要上传就能显示出图片的预览功能, 代码: <%@ Page Language="C#" AutoEventWireup ...
- 图片本地预览 flash html5
dataURI 一种能够在页面嵌入外部资源的URI方案.能够降低图片或者样式表的http请求数量,提高效率. ie8把dataURI 的属性值限制在32k以内. 图片本地预览: 由于安全原因,通过fi ...
- 巧用weui.gallery(),点击图片后预览图片
要在页面需要加载的JS文件: <script src="../js/libs/weui.min.js"></script> 可以去weui的文档中下载,这是 ...
- 微信小程序图片放大预览
需求:当点击图片时,当前图片放大预览,且可以左右滑动 实现方式:使用微信小程序图片预览接口 我们可以看到api需要两个参数,分别通过下面的data-list和data-src来传到js中 wxml代码 ...
- node.js平台下,cropper.js实现图片裁剪预览并转换为base64发送至服务端。
一 .准备工作 1.首先需要先下载cropper,常规使用npm,进入项目路径后执行以下命令: npm install cropper 2. cropper基于jquery,在此不要忘记引入jq,同时 ...
- iOS HTML图片本地预览
引言 相信用过苹果手机的童鞋,会发现很多新闻类的应用,都可以实现HTML图片本地预览,那么这是如何实现的呢?本文将深入阐述其中的原理. 关于此功能,我还实现了一个DEMO,大家可以点击此访问更详细内容 ...
- JS实现图片base64转blob对象,压缩图片,预览图片,图片旋转到正确角度
base64转blob对象 /** 将base64转换为文件对象 * @param {String} base64 base64字符串 * */ var convertBase64ToBlob = f ...
随机推荐
- php多行字符串输出
$content_header =<<<CONTENT_HEADER <section class="content-header"> <h ...
- Lsp修复
打开电脑,进入命令提示符窗口,快捷键win+r. 在窗口中输入“cmd”进入命令符窗口. 在窗口中输入:输入netsh winsock reset,然后按下回车键. 然后稍等片刻, ...
- 1.1机器学习基础-python深度机器学习
参考彭亮老师的视频教程:转载请注明出处及彭亮老师原创 视频教程: http://pan.baidu.com/s/1kVNe5EJ 1. 课程介绍 2. 机器学习 (Machine Learning, ...
- django框架的网站发布后设置是否允许被别人iframe引用
例如: <iframe src="http://127.0.0.1:8008" style="width:100%;height:400px;">& ...
- SQL脚本小笔记
--表添加字段.说明--- --脚本 alter table 表名 ADD 字段名 FLOAT(类型) NOT NULL Default 0(默认值) EXECUTE sp_addextendedpr ...
- Reporting Services 钻取报表、子报表
一.钻取报表 1.概念 钻取报表是指用户通过单击其他报表中的链接打开的报表.钻取报表通常包含某原始汇总报表中所包含的某项的详细信息. 例如,在此图中,销售额汇总报表列出了销售订单和总额.当用户单击该汇 ...
- String、StringBuffer和StringBuilder的区别
1 String String:字符串常量,字符串长度不可变.Java中String是immutable(不可变)的. String类的包含如下定义: /** The value is used fo ...
- Android开源项目发现--- 传感器篇(持续更新)
Great Android Sensing Toolkit Android感应器工具包,包含示例及使用过程中可能需要的算法 项目地址:https://github.com/gast-lib/gast- ...
- Hadoop上结合opencv\javacv
mac上安装opencv 1. 去 http://opencv.org 下载最新版OpenCV for Linux/Mac源文件,目前版本是2.4.3.下载后解压.2. 去 http://www.cm ...
- Java中类Exchaner浅析
Exchaner用于实现两个人之间的数据交换,每个人在完成一定的事物后想与对方交换数据,第一个先拿出数据的人将一直等待第二个人拿着数据到来时,才能彼此交换数据. 张孝祥老师在讲解Exchaner时的比 ...