android之实现打开相册、拍照录像、播放视频、保存图片到系统相册\指定位置、图片压缩

本文主要是介绍android之实现打开相册、拍照录像、播放视频、保存图片到系统相册\指定位置、图片压缩,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

打开相册选择图片裁剪:https://blog.csdn.net/Code_legend/article/details/77620359

https://blog.csdn.net/zz110753/article/details/60877594

图片选择框架:星级最多https://github.com/LuckSiege/PictureSelector

https://github.com/wildma/PictureSelector

https://github.com/HuanTanSheng/EasyPhotos

 

自定义的一些请求码:

private static final int CODE_GALLERY_REQUEST = 0xa0;
private static final int CODE_CAMERA_REQUEST = 0xa1;
private static final int CODE_RESULT_REQUEST = 0xa2;
private static final int CAMERA_PERMISSIONS_REQUEST_CODE = 0x03;
private static final int STORAGE_PERMISSIONS_REQUEST_CODE = 0x04;
private static final int CHOOSE_PHOTO = 0x05;

检查权限、动态请求权限、权限回调

 /*** 动态申请sdcard读写权限*/private void autoObtainStoragePermission() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSIONS_REQUEST_CODE);} else {}} else {}}/**自Android 6.0以后对某些涉及用户隐私权限的获取需要动态获取,所以首先是检查权限,如没有权限则动态申请权限,这里我们需要用到的权限是WRITE_EXTERNAL_STORAGE和CAMERA。* FileProvider是ContentProvider的一个子类,用于应用程序之间私有文件的传递。自Android 7.0后系统禁止应用向外部公开file://URI ,* 因此需要FileProvider来向外界传递URI,传递的形式是content : //Uri,使用时需要在清单文件中注册。*** 申请访问相机权限*/private void autoObtainCameraPermission() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (checkPermission()) {//检查权限//没有权限,发送权限请求if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.CAMERA)) {Toast.makeText(getActivity(), "您已经拒绝过一次了", Toast.LENGTH_SHORT).show();}//请求相机权限requestPermissions();} else {//有权限直接调用系统相机拍照if (hasSdcard()) {//sd卡挂载上了,可读可写//打开相机} else {Toast.makeText(getActivity(), "没有SD卡", Toast.LENGTH_SHORT).show();}}}}//检查权限private boolean checkPermission() {//是否有权限boolean haveCameraPermission = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;boolean haveWritePermission = ContextCompat.checkSelfPermission(getActivity(),Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;return haveCameraPermission && haveWritePermission;}// 请求相机权限和sd卡权限@RequiresApi(api = Build.VERSION_CODES.M)private void requestPermissions() {requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, CAMERA_PERMISSIONS_REQUEST_CODE);}//请求权限的回调@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {Log.d(TAG, "onRequestPermissionsResult: ");super.onRequestPermissionsResult(requestCode, permissions, grantResults);switch (requestCode) {//调用系统相机申请拍照权限回调case CAMERA_PERMISSIONS_REQUEST_CODE: {if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {//允许授权if (hasSdcard()) {
//拍照} else {Toast.makeText(getActivity(), "没有SD卡", Toast.LENGTH_SHORT).show();}} else {Toast.makeText(getActivity(), "请允许打开相机", Toast.LENGTH_SHORT).show();}break;}//调用系统相册申请Sdcard权限回调case STORAGE_PERMISSIONS_REQUEST_CODE:if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//打开相册} else {Toast.makeText(getActivity(), "请允许操作SD卡", Toast.LENGTH_SHORT).show();}break;default:}}/*** 检查设备是否存在SDCard的工具方法*/public static boolean hasSdcard() {String state = Environment.getExternalStorageState();return state.equals(Environment.MEDIA_MOUNTED);}

拍照

系统相机拍照:

1.//定义一个保存图片的File变量 private File currentImageFile = null; private Uri currentImageUri=null;

/**** 自己定义一个保存路径,(拍完的图片是不会保存到本地的, 我们可以自己写代码把图片保存到我们的SD卡里,然后再显示,这样的图片会清晰很多.)* */public void createSavepath(){File dir = new File(Environment.getExternalStorageDirectory(),"pictures");if(!dir.exists()){dir.mkdirs();}currentImageFile = new File(dir,System.currentTimeMillis() + ".jpg");if(!currentImageFile.exists()){try {currentImageFile.createNewFile();} catch (IOException e) {e.printStackTrace();}}Log.d("extra",""+dir.toString());
}

2.在res下面创建一个xml文件夹,xml下面建立file_paths.xml文件,这个文件的主要作用是向外提供content://uri路径。

<paths xmlns:android="http://schemas.android.com/apk/res/android"><!--files-path  相当于 getFilesDir()--><files-path name="my_images" path="images"/><!--cache-path  相当于 getCacheDir()--><cache-path name="lalala" path="cache_image"/><!--external-path  相当于 Environment.getExternalStorageDirectory()--><external-path  name="hahaha" path="."/><!--external-files-path  相当于 getExternalFilesDir("") --><external-files-path name="paly" path="freeSoft"/><!--external-cache-path  相当于 getExternalCacheDir() --><external-cache-path  name="lei" path="."/></paths>

3.manifest配置:application下面添加provide配置

<application><providerandroid:name="android.support.v4.content.FileProvider"android:authorities="com.example.wofu.aichi010.fileprovider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths" /></provider>
</application>

权限:

<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

4.打开相机,需要动态添加权限

方法一:这种方法是自定义路径存储图片createSavepath();//上面自定义保存路径currentImageUri =  FileProvider.getUriForFile(getActivity(), "com.example.wofu.aichi010.fileprovider" ,currentImageFile);//打开相机Intent it = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);it.putExtra(MediaStore.EXTRA_OUTPUT,currentImageUri);//输出到指定路径it.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);//授予临时权限startActivityForResult(it, Activity.DEFAULT_KEYS_DIALER);

 

方法二:这种方法不存储图片,

Intent it = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(it,Activity.DEFAULT_KEYS_DIALER);

 

5.回调获取图片

 //重写onActivityResult方法,相机拍照后会返回一个intent给onActivityResult。 intent的extra部分包含一个编码过的Bitmap,// 拍完的图片是不会保存到本地的, 我们可以自己写代码把图片保存到我们的SD卡里,然后再显示,这样的图片会清晰很多.@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {Log.d("回调图片","照片"+resultCode+data+requestCode);if (resultCode == Activity.RESULT_OK) {
方式一:自定义路径中获取图片
img_show.setImageURI(currentImageUri);方式二:直接使用图片,不存储,img_show是ImageviewBundle bundle = data.getExtras();Bitmap bitmap = (Bitmap) bundle.get("data");img_show.setImageBitmap(bitmap);}}

 

 

自定义相机拍照:

 

 

 

保存图片

---------------保存图片到指定位置---------

 

将Bitmap保存图片到指定的路径/sdcard/Boohee/下,文件名以当前系统时间命名,但是这种方法保存的图片没有加入到系统图库中

public static File saveImage(Bitmap bmp) {File appDir = new File(Environment.getExternalStorageDirectory(), "Boohee");if (!appDir.exists()) {appDir.mkdir();}String fileName = System.currentTimeMillis() + ".jpg";File file = new File(appDir, fileName);try {FileOutputStream fos = new FileOutputStream(file);bmp.compress(CompressFormat.JPEG, 100, fos);fos.flush();fos.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}
}

———————保存图片到系统相册-------

调用以上系统自带的方法会把bitmap对象保存到系统图库中, 但是这种方法无法指定保存的路径和名称, 上述方法的title、description参数只是插入数据库中的字段, 真实的图片名称系统会自动分配。插入图库的方法图片并没有立刻显示在图库中,而我们需要立刻更新系统图库以便让用户可以立刻查看到这张图片。

MediaStore.Images.Media.insertImage(getActivity().getContentResolver(), bitmap, "title", "description");

 

录像

1.创建路线个保存路径:

//定义一个保存视频的File变量
private File currentImageFile = null;
private Uri currentImageUri=null;
public void createvideoSavepath(){File dir = new File(Environment.getExternalStorageDirectory(),"videos");if(!dir.exists()){dir.mkdirs();}currentImageFile = new File(dir,System.currentTimeMillis() + ".mp4");if(!currentImageFile.exists()){try {currentImageFile.createNewFile();} catch (IOException e) {e.printStackTrace();}}Log.d("extra",""+dir.toString());
}

2.打开相机录像,fileprovide的配置参考相机拍照

createvideoSavepath();
currentImageUri =  FileProvider.getUriForFile(getActivity(), "com.example.wofu.aichi010.fileprovider" ,currentImageFile);
Intent intents = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
intents.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
intents.putExtra(MediaStore.EXTRA_OUTPUT, currentImageUri);
startActivityForResult(intents, 10);

3.录像后回调

public void onActivityResult(int requestCode, int resultCode, Intent data) {Log.d("回调图片","照片"+resultCode+data+requestCode);if (resultCode == Activity.RESULT_OK) {}

 

 

打开相册

***从相册选择video

 

/*** 从相册中选择视频*/
private void choiceVideo() {Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI);startActivityForResult(i, 66);}protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == 66 && resultCode == RESULT_OK && null != data) {Uri selectedVideo = data.getData();String[] filePathColumn = {MediaStore.Video.Media.DATA};Cursor cursor = getContentResolver().query(selectedVideo,filePathColumn, null, null, null);cursor.moveToFirst();int columnIndex = cursor.getColumnIndex(filePathColumn[0]);VIDEOPATH = cursor.getString(columnIndex);cursor.close();//根据时间路径播放视频       }if (resultCode != Activity.RESULT_OK) {return;}}

 

*****打开相册

方式一:这种方式会打开,页面显示错误报告、图库、文件管理,近期的图片页面,图片、视频、文件都可以选择

Intent intent = new Intent("android.intent.action.GET_CONTENT");
intent.setType("image/*");
startActivityForResult(intent, CHOOSE_PHOTO); // 打开相册

 

方式二:打开选择图片,显示的是一个个图片文件夹

Intent intentFromGallery = new Intent();
// 设置文件类型
intentFromGallery.setType("image/*");
intentFromGallery.setAction(Intent.ACTION_PICK);
startActivityForResult(intentFromGallery, CODE_GALLERY_REQUEST);

打开相册的回调:

public void onActivityResult(int requestCode, int resultCode, Intent data) {Log.d("回调图片","照片"+resultCode+data+requestCode);if (resultCode == Activity.RESULT_OK) {

//获取Bitmap,然后加载图片

Uri uri = data.getData();
ContentResolver resolver = getActivity().getContentResolver();
try {Bitmap bitmap = MediaStore.Images.Media.getBitmap(resolver,uri);img_show.setImageBitmap(bitmap);
} catch (IOException e) {e.printStackTrace();
}//获取一些图片信
//Uri uri = data.getData();
//Cursor cursor =getActivity().getContentResolver().query(uri, null, null, null,null);
//if (cursor != null && cursor.moveToFirst()) {//这里开始查询每一列的信息,有6列//  String path = cursor.getString(1);//0是内存地址,1是图片格式,如image/jpeg//  Log.d("相册选择",path);// cursor.close();
//}
}

 

压缩图片

调用:

  try {Bitmap  bitmap  =   getBitmapFormUri(currentImageUri);img_show.setImageBitmap(bitmap);} catch (IOException e) {e.printStackTrace();}
 //缩放图片public Bitmap getBitmapFormUri(Uri uri) throws FileNotFoundException, IOException {InputStream input = getContext().getContentResolver().openInputStream(uri);//这一段代码是不加载文件到内存中也得到bitmap的真是宽高,主要是设置inJustDecodeBounds为trueBitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();onlyBoundsOptions.inJustDecodeBounds = true;//不加载到内存onlyBoundsOptions.inDither = true;//optionalonlyBoundsOptions.inPreferredConfig = Bitmap.Config.RGB_565;//optionalBitmapFactory.decodeStream(input, null, onlyBoundsOptions);input.close();int originalWidth = onlyBoundsOptions.outWidth;int originalHeight = onlyBoundsOptions.outHeight;if ((originalWidth == -1) || (originalHeight == -1))return null;//图片分辨率以480x800为标准float hh = 800f;//这里设置高度为800ffloat ww = 480f;//这里设置宽度为480f//缩放比,由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可int be = 1;//be=1表示不缩放if (originalWidth > originalHeight && originalWidth > ww) {//如果宽度大的话根据宽度固定大小缩放be = (int) (originalWidth / ww);} else if (originalWidth < originalHeight && originalHeight > hh) {//如果高度高的话根据宽度固定大小缩放be = (int) (originalHeight / hh);}if (be <= 0)be = 1;//比例压缩BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();bitmapOptions.inSampleSize = be;//设置缩放比例bitmapOptions.inDither = true;bitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;input = getActivity().getContentResolver().openInputStream(uri);Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);input.close();return compressImage(bitmap);//再进行质量压缩}//压缩图片质量public Bitmap compressImage(Bitmap image) {ByteArrayOutputStream baos = new ByteArrayOutputStream();image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中int options = 100;while (baos.toByteArray().length / 1024 > 100) {  //循环判断如果压缩后图片是否大于100kb,大于继续压缩baos.reset();//重置baos即清空baos//第一个参数 :图片格式 ,第二个参数: 图片质量,100为最高,0为最差  ,第三个参数:保存压缩后的数据的流image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options,把压缩后的数据存放到baos中options -= 10;//每次都减少10if (options<=0)break;}ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片return bitmap;}

 

---------------播放视频-----------------

public class MainActivity extends AppCompatActivity {private MediaPlayer mediaPlayer;private SurfaceView sfv;private VideoView vv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);setSupportActionBar(toolbar);sfv = findViewById(R.id.sfv);//可以在子线程直接更新UI//播放视频public  void play(){mediaPlayer = new MediaPlayer();try {mediaPlayer.setDataSource("http://badu.com/ddd");//要播放的数据} catch (IOException e) {e.printStackTrace();}mediaPlayer.prepareAsync();//准备播放//设置显示final SurfaceHolder holder=sfv.getHolder();holder.addCallback(new SurfaceHolder.Callback() {private int cur;//sfv准备好了@Overridepublic void surfaceCreated(SurfaceHolder surfaceHolder) {mediaPlayer.setDisplay(holder);//准备完成再开始播放mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {@Overridepublic void onPrepared(MediaPlayer mediaPlayer) {mediaPlayer.start();mediaPlayer.seekTo(cur);//上次的位置}});}
//变化的时候@Overridepublic void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {}
//sfv销毁的时候@Overridepublic void surfaceDestroyed(SurfaceHolder surfaceHolder) {if(mediaPlayer!=null && mediaPlayer.isPlaying()) {//获取视频当前位置cur = mediaPlayer.getCurrentPosition();mediaPlayer.stop();//停止}}});}//方法二:videoview实现视频播放public  void videoViewPlay(){
//videoView控件就是对surfaceView的封装,实现mediaplayer接口vv = findViewById(R.id.videoV);vv.setVideoPath("http://bas.com/ee.mp4");//播放的资源
vv.start();//开始播放}//方法三:vitamio框架实现视频播放public  void vitamioMobviePlay(){}}

 

这篇关于android之实现打开相册、拍照录像、播放视频、保存图片到系统相册\指定位置、图片压缩的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1017720

相关文章

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

JAVA读取MongoDB中的二进制图片并显示在页面上

1:Jsp页面: <td><img src="${ctx}/mongoImg/show"></td> 2:xml配置: <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001

通过SSH隧道实现通过远程服务器上外网

搭建隧道 autossh -M 0 -f -D 1080 -C -N user1@remotehost##验证隧道是否生效,查看1080端口是否启动netstat -tuln | grep 1080## 测试ssh 隧道是否生效curl -x socks5h://127.0.0.1:1080 -I http://www.github.com 将autossh 设置为服务,隧道开机启动

通信系统网络架构_2.广域网网络架构

1.概述          通俗来讲,广域网是将分布于相比局域网络更广区域的计算机设备联接起来的网络。广域网由通信子网于资源子网组成。通信子网可以利用公用分组交换网、卫星通信网和无线分组交换网构建,将分布在不同地区的局域网或计算机系统互连起来,实现资源子网的共享。 2.网络组成          广域网属于多级网络,通常由骨干网、分布网、接入网组成。在网络规模较小时,可仅由骨干网和接入网组成

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测 目录 时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测基本介绍程序设计参考资料 基本介绍 MATLAB实现LSTM时间序列未来多步预测-递归预测。LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其他资料中LSTM区块可能被描述成智能网络单元,因为

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开

android 免费短信验证功能

没有太复杂的使用的话,功能实现比较简单粗暴。 在www.mob.com网站中可以申请使用免费短信验证功能。 步骤: 1.注册登录。 2.选择“短信验证码SDK” 3.下载对应的sdk包,我这是选studio的。 4.从头像那进入后台并创建短信验证应用,获取到key跟secret 5.根据技术文档操作(initSDK方法写在setContentView上面) 6.关键:在有用到的Mo

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现