1)Android中開啟攝像頭的主要步驟
2)傳感器調用
一. 拍照及獲取本地相冊
1.1 添加權限:
<!-- 往SDCard寫入數(shù)據(jù)權限 -->
<uses-permission android:name="android.permission.
WRITE_EXTERNAL_STORAGE" />
<!--請求訪問使用照相設備-->
<uses-permission android:name="android.permission.CAMERA" />
1.2 設置標志(回傳碼)
// 拍照回傳碼
public final static int CAMERA_REQUEST_CODE = 0;
// 相冊選擇回傳碼
public final static int GALLERY_REQUEST_CODE = 1;
若多個地方使用了這個拍照功能 可以放在公共類中仪搔,設置為全局變量
1.3 在相應的java類中
// 拍照的照片的存儲位置
private String mTempPhotoPath;
// 照片所在的Uri地址
private Uri imageUri;
1.4 點擊拍照事件中
動態(tài)申請權限:
// 第二個參數(shù)是需要申請的權限
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) { //權限還沒有授予,需要在這里寫申請權限的代碼
// 第二個參數(shù)是一個字符串數(shù)組呻拌,里面是你需要申請的權限 可以設置申請多個權限
// 最后一個參數(shù)是標志你這次申請的權限萌朱,該常量在onRequestPermissionsResult中使用到
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
GlobalVariable.CAMERA_REQUEST_CODE);
} else { //權限已經被授予,在這里直接寫要執(zhí)行的相應方法即可
takePhoto();
}
1.5 拍照實現(xiàn)方法
private void takePhoto(){
// 跳轉到系統(tǒng)的拍照界面
Intent intentToTakePhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 指定照片存儲位置為sd卡本目錄下
// 這里設置為固定名字 這樣就只會只有一張temp圖 如果要所有中間圖片都保存可以通過時間或者加其他東西設置圖片的名稱
// File.separator為系統(tǒng)自帶的分隔符 是一個固定的常量
mTempPhotoPath = Environment.getExternalStorageDirectory() + File.separator + "photo.jpeg";
// 獲取圖片所在位置的Uri路徑 *****這里為什么這么做參考問題2*****
/*imageUri = Uri.fromFile(new File(mTempPhotoPath));*/
imageUri = FileProvider.getUriForFile(MainActivity.this,
MainActivity.this.getApplicationContext().getPackageName() +".my.provider",
new File(mTempPhotoPath));
//下面這句指定調用相機拍照后的照片存儲的路徑
intentToTakePhoto.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intentToTakePhoto, GlobalVariable.CAMERA_REQUEST_CODE);
}
1.6 打開本地相冊事件
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) { //權限還沒有授予红省,需要在這里寫申請權限的代碼
// 第二個參數(shù)是一個字符串數(shù)組额各,里面是你需要申請的權限 可以設置申請多個權限
// 最后一個參數(shù)是標志你這次申請的權限,該常量在onRequestPermissionsResult中使用到
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
GlobalVariable.CAMERA_REQUEST_CODE);
} else { //權限已經被授予吧恃,在這里直接寫要執(zhí)行的相應方法即可
choosePhoto();
}
}
1.7 打開相冊方法實現(xiàn)
private void choosePhoto(){
Intent intentToPickPic = new Intent(Intent.ACTION_PICK, null);
// 如果限制上傳到服務器的圖片類型時可以直接寫如:"image/jpeg 虾啦、 image/png等的類型" 所有類型則寫 "image/*"
intentToPickPic.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/jpeg");
startActivityForResult(intentToPickPic, GlobalVariable.GALLERY_REQUEST_CODE);
}
1.8 界面回調方法 用于將得到的照片處理
//當拍攝照片完成時會回調到onActivityResult 在這里處理照片的裁剪
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
fragment4ImageView0 = findViewById(R.id.fragment4ImageView0);
if (resultCode == MainActivity.RESULT_OK) {
switch (requestCode) {
case GlobalVariable.CAMERA_REQUEST_CODE: {
// 獲得圖片
try {
//該uri就是照片文件夾對應的uri
Bitmap bit = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
// 給相應的ImageView設置圖片 未裁剪
fragment4ImageView0.setImageBitmap(bit);
} catch (Exception e) {
e.printStackTrace();
}
break;
}
case GlobalVariable.GALLERY_REQUEST_CODE: {
// 獲取圖片
try {
//該uri是上一個Activity返回的
imageUri = data.getData();
if(imageUri!=null) {
Bitmap bit = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
Log.i("bit", String.valueOf(bit));
fragment4ImageView0.setImageBitmap(bit);
}
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
}
super.onActivityResult(requestCode, resultCode, data);
}
1.9 權限申請回調方法
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
{
if (requestCode == GlobalVariable.CAMERA_REQUEST_CODE)
{
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
takePhoto();
} else
{
// Permission Denied
Toast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_SHORT).show();
}
}
if (requestCode == GlobalVariable.GALLERY_REQUEST_CODE)
{
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
choosePhoto();
} else
{
// Permission Denied
Toast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_SHORT).show();
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
1.10 Android N(7.0)版本以上
android.os.FileUriExposedException:
file:///storage/emulated/0/photo.jpeg exposed beyond app through ClipData.Item.getUri()
1. 創(chuàng)建一個類 繼承FileProvider
public class GenericFileProvider extends FileProvider {
}
**2. Manifest.xml的application中 **
<provider
android:name=".Utils.GenericFileProvider"
android:authorities="${applicationId}.my.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
3. res/xml目錄下 若沒有 xml目錄則創(chuàng)建
創(chuàng)建 provider_paths.xml文件
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
4. 使用
/*imageUri = Uri.fromFile(new File(mTempPhotoPath));*/
替換成:
imageUri = FileProvider.getUriForFile(MainActivity.this,
MainActivity.this.getApplicationContext().getPackageName() +".my.provider",
new File(mTempPhotoPath));
二. Android 傳感器的調用
package com.bobo.study.study_5_1;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
//1,獲得SensorManager對象
//2,獲得想要的Sensor對象
//3,綁定監(jiān)聽器
public class MainActivity extends Activity implements View.OnClickListener{
Button findBut,accelerationBut,lightBut,orientationBut,proximityBut;
SensorManager sensorManager;
TextView text,accText,luxText;
float gravity[]=new float[3];
float linear_acceleration[]=new float[3];
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findBut=(Button)findViewById(R.id.findBut);
findBut.setOnClickListener(this);
lightBut=(Button)findViewById(R.id.lightBut);
lightBut.setOnClickListener(this);
accelerationBut=(Button)findViewById(R.id.accelerationBut);
accelerationBut.setOnClickListener(this);
orientationBut=(Button)findViewById(R.id.orientationBut);
orientationBut.setOnClickListener(this);
proximityBut=(Button)findViewById(R.id.proximityBut);
proximityBut.setOnClickListener(this);
text=(TextView)findViewById(R.id.text);
accText=(TextView)findViewById(R.id.accText);
luxText=(TextView)findViewById(R.id.luxText);
//獲得傳感器管理器對象
sensorManager=(SensorManager)getSystemService(Context.SENSOR_SERVICE);
}
@Override
public void onClick(View v) {
if(v==findBut){
//獲取手機上所有傳感器的列表
List<Sensor> sensors=sensorManager.getSensorList(Sensor.TYPE_ALL);
for(Sensor sensor:sensors){
System.out.println(sensor.getName());
}
}else if(v==lightBut){
//得到默認的加速度傳感器
Sensor lightSensor=sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
//綁定監(jiān)聽器(上下文接口,要監(jiān)聽的傳感器痕寓,傳感器采樣率<時間間隔>),返回結果
Boolean res=sensorManager.registerListener(new LightSensorListener(),lightSensor,SensorManager.SENSOR_DELAY_NORMAL);
Toast.makeText(this,"綁定光線傳感器:"+res,Toast.LENGTH_LONG).show();
}
else if(v==accelerationBut){
Sensor accelerometerSensor=sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
Boolean res=sensorManager.registerListener(new AccerationSensorListener(),accelerometerSensor,SensorManager.SENSOR_DELAY_NORMAL);
Toast.makeText(this,"綁定加速度傳感器:"+res,Toast.LENGTH_LONG).show();
}else if(v==orientationBut){
Sensor orientationSensor=sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
Boolean res=sensorManager.registerListener(new OrientaationListener(),orientationSensor,SensorManager.SENSOR_DELAY_NORMAL);
Toast.makeText(this,"綁定方向傳感器:"+res,Toast.LENGTH_LONG).show();
}
else if(v==proximityBut){
Sensor proximitySensor=sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
Boolean res=sensorManager.registerListener(new ProximityListener(),proximitySensor,SensorManager.SENSOR_DELAY_NORMAL);
Toast.makeText(this,"綁定距離傳感器:"+res,Toast.LENGTH_LONG).show();
}
}
public class LightSensorListener implements SensorEventListener{
@Override
//傳感器的數(shù)據(jù)被打包成event傲醉,主要的檢測數(shù)據(jù)放在enent.values[]數(shù)組中
public void onSensorChanged(SensorEvent event) {
System.out.println(event.timestamp);//時間戳
System.out.println(event.sensor.getResolution());//分辨率(能識別出最小數(shù)值)
System.out.println(event.accuracy);//精度(等級)
System.out.println(event.values[0]);//光線強度
}
@Override
//傳感器精度變化時調用這個函數(shù)
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
}
public class AccerationSensorListener implements SensorEventListener{
@Override
public void onSensorChanged(SensorEvent event) {
final float alpha=0.8f;
//event.values[0]X軸加速度,負方向為正
//event.values[1]Y軸加速度呻率,負方向為正
//event.values[2]Z軸加速度硬毕,負方向為正
gravity[0]=alpha*gravity[0]+(1-alpha)*event.values[0];
gravity[1]=alpha*gravity[1]+(1-alpha)*event.values[1];
gravity[2]=alpha*gravity[2]+(1-alpha)*event.values[2];
linear_acceleration[0]=event.values[0]-gravity[0];
linear_acceleration[1]=event.values[1]-gravity[1];
linear_acceleration[2]=event.values[2]-gravity[2];
//通過以上公式可以拋去三個方向上的重力加速度,只剩下純加速度
text.setText(linear_acceleration[0] + "");
accText.setText(linear_acceleration[1] + "");
luxText.setText(linear_acceleration[2] + "");
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
}
public class OrientaationListener implements SensorEventListener{
@Override
public void onSensorChanged(SensorEvent event) {
//(需要手機屏幕向上礼仗,向下的話南北會反掉)設備繞Z軸旋轉昭殉,Y軸正方向與地磁北極方向的夾角苞七,順時針方向為正,范圍【0挪丢,180】
float azimuth=event.values[0];
//設備繞X軸旋轉的角度蹂风,當Z軸向Y軸正方向旋轉時為正,反之為負乾蓬,范圍【-180,180】
float pitch=event.values[1];
//設備繞Y軸旋轉的角度惠啄,當Z軸向X軸正方向旋轉時為負,反之為正任内,范圍【-90,90】
float roll=event.values[2];
text.setText(azimuth+"");
accText.setText(pitch +"");
luxText.setText(roll+"");
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
}
public class ProximityListener implements SensorEventListener{
@Override
public void onSensorChanged(SensorEvent event) {
//距離傳感器測試手機屏幕距離別的物體的記錄撵渡,只有兩個值:0和5
//距離很近時為0,否則為5
System.out.println(event.values[0]+"");
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
https://blog.csdn.net/weixin_37577039/article/details/79186183
https://blog.csdn.net/youmingyu/article/details/52750374