Android之多媒体技术

Canvas canvas = new Canvas(copyBitmap);

//2.2 创建画笔

Paint paint = new Paint();

//2.3 开始作画 srcBitmap参考原图作画

canvas.drawBitmap(srcBitmap, new Matrix(), paint);

4. 图形的处理api

============

  • 旋转

// 参数 旋转角度,旋转的中点x,y

matrix.setRotate(degrees, srcBitmap.getWidth() / 2,srcBitmap.getHeight() / 2);

  • 缩放 matrix.setScale(0.5f, 0.5f);

  • 位移 matrix.setTranslate(80, 0);

  • 倒影效果

matrix.setScale(1.0f, -1.0f); //x轴不变 y轴反转

//post是在上一次修改的基础上进行修改,set则是每次都是新的变化 会覆盖上一次的修改

matrix.postTranslate(0, srcBitmap.getHeight());

  • 镜面效果

matrix.setScale(-1.0f, 1.0f);

matrix.postTranslate(srcBitmap.getWidth(), 0);

  • 设置像素点透明

alterbBitmap.setPixel((int)event.getX()+i, (int)event.getY()+j, Color.TRANSPARENT);

5. 使用MediaPlayer播放音频文件

=======================

作用:这个类可用于播放音频或者视频

6. 百度音乐盒完成

===========

  1. 获取当前歌曲进度和总时长

private void updateSeekBar() {

//6. 获取音乐文件的总时长 Gets the duration of the file.

final int duration = mediaPlayer.getDuration();

//7. 构造定时器

Timer timer = new Timer();

//7.1 创建任务

TimerTask timerTask = new TimerTask() {

@Override

public void run() {

//8. 获取歌曲的当前进度

int currentPosition = mediaPlayer.getCurrentPosition();

//9. 通过handler发送歌曲的信息到Activity更新UI

//9.1 通过将数据封装到Message中

Message msg = new Message();

//9.2 封装多条数据到Message中 将那些数据封装到Bundle中,其实Bundle底层就是Map

Bundle bundle = new Bundle();

bundle.putInt(“duration”, duration);

bundle.putInt(“currentPosition”, currentPosition);

msg.setData(bundle);

//10. 发送数据

MainActivity.handler.sendMessage(msg);

}

};

//7.2 300毫秒后 每隔1秒执行一次任务

timer.schedule(timerTask, 300, 1000); //每隔1秒获取歌曲的进度

}

  1. 在服务中添加一个播放进度的方法

/**

  • 设置播放音乐指定位置的方法

  • @param position 该位置由进度条拖动时提供

*/

private void seekToPosition(int position){

mediaPlayer.seekTo(position);

}

  1. 通过handler将数据传递到Activity更新UI

  2. SeekBar处理数据

sb_seekm.setMax(duration); //设置进度条最大值

sb_seekm.setProgress(currentPosition); //设置进度条当前进度

7. SurfaceView介绍

=================

  • SurfaceView控件是一个重量级控件

  • 内部维护了2个线程

  • A 获取数据 负责显示

  • B 负责显示 获取数据

  • 它直接可以在子线程更新UI 与进度相关的控件可以直接在子线程更新Ui

//找到控件

final SurfaceView sfv = (SurfaceView) findViewById(R.id.sfv);

final SurfaceHolder surfaceHolder = sfv.getHolder();

//添加一个callback

surfaceHolder.addCallback(new Callback() {

//当surfaceview销毁的时候调用

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

System.out.println(“surfaceDestroyed”);

if (player!=null && player.isPlaying()) {

//获取当前视频播放的位置

currentPosition = player.getCurrentPosition();

player.stop();

}

}

//当surfaceview 初始化了

@Override

public void surfaceCreated(SurfaceHolder holder) {

//[1]初始化mediaplayer

player = new MediaPlayer();

//[2]设置要播放的资源 path 可以是本地也可是网络路径

try {

player.setDataSource(“http://192.168.13.89:8080/cc.MP4”);

//[2.1]设置播放视频的内容 SurfaceHolder 是用来维护视频播放的内容

player.setDisplay(surfaceHolder);

//[3]准备播放

// player.prepare();

player.prepareAsync();

//设置一个准备完成的监听

player.setOnPreparedListener(new OnPreparedListener() {

@Override

public void onPrepared(MediaPlayer mp) {

//[4]开始播放

player.start();

//[5]继续上次的位置继续播放

player.seekTo(currentPosition);

}

});

} catch (Exception e) {

e.printStackTrace();

}

}

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width,

int height) {

}

});

补充1 VideoView

  • 这个控件就是对SurfaceView和MediaPlayer进行封装

  • MediaPlayer 播放视频只支持3gp mp4格式

  • 如果只是播放一些游戏的片头动画,或者某个应用的视频宣传,使用VideoView还是绰绰有余的.

补充2 vitamio框架

vitamio框架是开源的,可以播放大多数视频格式的框架.

8. 照相和录像

=========

// create Intent to take a picture and return control to the calling

// application

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

File file = new File(Environment.getExternalStorageDirectory(),

“1.png”);

intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));

// start the image capture Intent

startActivityForResult(intent, 1);

9. 调用摄像头拍照并显示

==============

下面的demo如果需要加载大图片,其实严谨的来说,应该加如图片缩放.有时候拍的照片太大了,以至于无法加载,程序报错.

  1. 首先我们决定将照片放到sd卡的应用缓存目录下,通过getExternalCacheDir()可以得到这个目录(具体的路径是/sdcard/Android/data/<package name>/cache).因为从Android6.0开始,读写SD卡被列为危险权限,如果将图片存放在SD卡的任何其他目录,都要进行运行时权限处理才行,而使用管理目录可以跳过这一步.

  2. 如果运行设备的系统版本低于Android 7.0,就调用Uri.fromFile()方法将File对象转换成Uri对象,这个Uri对象标识着图片的本地真实路径.

否则,就调用FileProvider的getUriForFile()方法将File对象转换成一个封装过的Uri对象.

之所以要进行这样一层转换,是因为从Android 7.0开始,直接使用本地真实路径的Uri被认为是不安全的,会抛出FileUriExposedException异常.而FileProvider则是一种特殊的内容提供器,它使用了和内容提供器类似的机制来对数据进行保护,可以选择性的将封装过的Uri共享给外部,从而提高了应用的安全性.

既然是内容提供器,则需要到清单文件中配置,具体配置如下:

<provider

android:authorities=“com.xfhy.cameraalbumtest.fileprovider”

android:name=“android.support.v4.content.FileProvider”

android:exported=“false”

android:grantUriPermissions=“true”>

<meta-data

android:name=“android.support.FILE_PROVIDER_PATHS”

android:resource=“@xml/file_paths”

/>

还需要在res目录下创建xml文件夹,然后新建File,file_paths.xml文件.写入如下内容:

<?xml version="1.0" encoding="utf-8"?>

其中external-path是用来指定Uri共享的,name属性的值可以随便填,path属性的值表示共享的具体路径,这里设置为空值表示将整个SD卡进行共享

还有一点需要注意,在Android 4.4系统之前,访问SD卡的应用关联目录也是要声明权限的,从4.4系统开始不再需要权限申明.那么我们为了能够兼容老版本的系统的手机,需要在清单文件中申明如下权限:

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

3.下面是具体的代码实现:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

private static final int TAKE_PHOTO = 1;

private static final String TAG = “MainActivity”;

private Button bt_take_photo; //拍照按钮

private Button bt_choose_from_album;

private ImageView iv_picture; //显示图片

private Uri imageUri; //标示图片路径的uri

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

bt_take_photo = (Button) findViewById(R.id.bt_take_photo);

bt_choose_from_album = (Button) findViewById(R.id.bt_choose_from_album);

iv_picture = (ImageView) findViewById(R.id.iv_picture);

bt_take_photo.setOnClickListener(this);

bt_choose_from_album.setOnClickListener(this);

}

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.bt_take_photo:

takePhoto();

break;

case R.id.bt_choose_from_album:

break;

default:

break;

}

}

/**

  • 调用摄像头拍照

*/

private void takePhoto() {

//1. 创建File对象,用于存储拍照后的图片

//这里的getExternalCacheDir()是应用的关联缓存目录,在SD卡下面(/sdcard/Android/data//cache)

//这里在Android 6.0运行时不用进行运行时权限处理

File outputImage = new File(getExternalCacheDir(), “output_image.jpg”);

//2. 判断文件是否存在

try {

if (outputImage.exists()) {

outputImage.delete();

outputImage.createNewFile();

}

} catch (IOException e) {

e.printStackTrace();

}

//3. 判断当前用户的设备的系统版本是否大于24(android 7.0)

if (Build.VERSION.SDK_INT >= 24) {

//4. 将File对象转化为一个封装好的Uri对象

imageUri = FileProvider.getUriForFile(MainActivity.this,

“com.xfhy.cameraalbumtest.fileprovider”,outputImage);

} else {

imageUri = Uri.fromFile(outputImage);

}

//5.启动相机程序

Intent intent = new Intent(“android.media.action.IMAGE_CAPTURE”);

intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);

startActivityForResult(intent,TAKE_PHOTO);

}

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

//请求码

switch (requestCode){

case TAKE_PHOTO:

//如果返回码是RESULT_OK,则是成功拍照了的

if(resultCode == RESULT_OK){

try {

//6. 将拍摄的照片显示出来

Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));

iv_picture.setImageBitmap(bitmap); //设置显示图片

Log.i(TAG, "onActivityResult: ");

} catch (FileNotFoundException e) {

e.printStackTrace();

}

}

break;

default:

break;

}

}

}

10. 从相册选择照片

============

读取相册中的照片,是需要申请读取SD卡权限.

根据系统版本是否是Android 4.4以上,有2种处理方式.之所以要这样做,是因为Android系统从4.4版本开始,选取相册中的图片不再返回图片的真实Uri了,而是一个封装过的Uri,因此如果是4.4版本以上的手机就需要对这个版本进行解析才行.

下面是demo

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

/**

  • 申请码

*/

private static final int TAKE_PHOTO = 1; //照相

private static final int CHOOSE_PHOTO = 2; //打开相册

private static final String TAG = “MainActivity”;

private Button bt_take_photo; //拍照按钮

private Button bt_choose_from_album;

private ImageView iv_picture; //显示图片

private Uri imageUri; //标示图片路径的uri

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

bt_take_photo = (Button) findViewById(R.id.bt_take_photo);

bt_choose_from_album = (Button) findViewById(R.id.bt_choose_from_album);

iv_picture = (ImageView) findViewById(R.id.iv_picture);

bt_take_photo.setOnClickListener(this);

bt_choose_from_album.setOnClickListener(this);

}

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.bt_take_photo:

takePhoto();

break;

case R.id.bt_choose_from_album:

requestPermission();

break;

default:

break;

}

}

/**

  • 申请权限 需要选择相册中的图片,则需要读SD卡的权限

*/

private void requestPermission() {

//检查是否有读SD卡的权限 不相等则需要申请权限

if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)

!= PackageManager.PERMISSION_GRANTED) {

//申请读SD的权限

ActivityCompat.requestPermissions(MainActivity.this,

new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);

} else {

openAlbum();

}

}

/**

  • 打开相册 进行图片选择

*/

private void openAlbum() {

//

Intent intent = new Intent(“android.intent.action.GET_CONTENT”);

intent.setType(“image/*”);

startActivityForResult(intent, CHOOSE_PHOTO); //打开相册

}

@Override

public void onRequestPermissionsResult(int requestCode,

@NonNull String[] permissions, @NonNull int[] grantResults) {

switch (requestCode) { //根据申请码进行判断

case 1:

//判断权限是否申请成功

if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

openAlbum();

} else {

Toast.makeText(this, “申请读SD卡权限失败”, Toast.LENGTH_SHORT).show();

}

break;

default:

break;

}

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

如何做好面试突击,规划学习方向?

面试题集可以帮助你查漏补缺,有方向有针对性的学习,为之后进大厂做准备。但是如果你仅仅是看一遍,而不去学习和深究。那么这份面试题对你的帮助会很有限。最终还是要靠资深技术水平说话。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。建议先制定学习计划,根据学习计划把知识点关联起来,形成一个系统化的知识体系。

学习方向很容易规划,但是如果只通过碎片化的学习,对自己的提升是很慢的。

我搜集整理过这几年字节跳动,以及腾讯,阿里,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节

img

在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

规划学习方向?**

面试题集可以帮助你查漏补缺,有方向有针对性的学习,为之后进大厂做准备。但是如果你仅仅是看一遍,而不去学习和深究。那么这份面试题对你的帮助会很有限。最终还是要靠资深技术水平说话。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。建议先制定学习计划,根据学习计划把知识点关联起来,形成一个系统化的知识体系。

学习方向很容易规划,但是如果只通过碎片化的学习,对自己的提升是很慢的。

我搜集整理过这几年字节跳动,以及腾讯,阿里,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节

img

在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值