Android基礎(33)傳感器和拍照棍丐、獲取本地相冊等

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

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末死嗦,一起剝皮案震驚了整個濱河市趋距,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌越除,老刑警劉巖节腐,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異摘盆,居然都是意外死亡翼雀,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門孩擂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狼渊,“玉大人,你說我怎么就攤上這事类垦”芬兀” “怎么了?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵蚤认,是天一觀的道長官地。 經常有香客問我,道長烙懦,這世上最難降的妖魔是什么驱入? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮氯析,結果婚禮上亏较,老公的妹妹穿的比我還像新娘。我一直安慰自己掩缓,他們只是感情好雪情,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著你辣,像睡著了一般巡通。 火紅的嫁衣襯著肌膚如雪尘执。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天宴凉,我揣著相機與錄音誊锭,去河邊找鬼。 笑死弥锄,一個胖子當著我的面吹牛丧靡,可吹牛的內容都是我干的。 我是一名探鬼主播籽暇,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼温治,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了戒悠?” 一聲冷哼從身側響起熬荆,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎绸狐,沒想到半個月后卤恳,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡六孵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了幅骄。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片劫窒。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖拆座,靈堂內的尸體忽然破棺而出主巍,到底是詐尸還是另有隱情,我是刑警寧澤挪凑,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布孕索,位于F島的核電站,受9級特大地震影響躏碳,放射性物質發(fā)生泄漏搞旭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一菇绵、第九天 我趴在偏房一處隱蔽的房頂上張望肄渗。 院中可真熱鬧,春花似錦咬最、人聲如沸翎嫡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽惑申。三九已至具伍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間圈驼,已是汗流浹背人芽。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留碗脊,地道東北人啼肩。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像衙伶,于是被迫代替她去往敵國和親祈坠。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內容