Android学习笔记(八)使用多媒体(通知、短信、摄像头、相册、音视频)
来源:互联网 发布:旅程网络 官网 编辑:程序博客网 时间:2024/06/05 17:58
8.1 通知(Notification)
当某个应用程序不在前台运行,但又希望给用户发送一些信息的时候,就可以借助通知来实现。
通知较为灵活,可在活动、广播接收器以及服务中创建,但实际应用中在活动中创建较少。
注意:
《第一行代码》原作中创建通知的方式已过时,现已更新为如下方式,简单示例:
/** * 1.创建一个通知管理对象 * getSystemService方法接收一个参数,用于确定获取系统的哪个服务 * 这里传入 Context.NOTIFICATION_SERVICE 即可 */NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);/** * 2.创建一个通知构造器builder对象 * param:Context上下文 */Notification.Builder builder = new Notification.Builder(MainActivity.this);//瞬时信息(通知刚被创建时,在系统栏一闪而过)builder.setTicker("有新通知啦快来查看!");//通知图标builder.setSmallIcon(R.drawable.android);//通知标题builder.setContentTitle("This is title");//通知内容builder.setContentText("Content....");//通知时间(显示在通知上)builder.setWhen(System.currentTimeMillis());//设置通知在点击后是否自动取消,默认falsebuilder.setAutoCancel(true);/** * 3.创建一个意图,用于指定点击该通知想要跳转到哪个Activity中 */Intent intent = new Intent(MainActivity.this, NotificationActivity.class);/** * 4.创建一个PendingIntent * PendingIntent,可简单理解为延迟执行的Intent,更倾向于在某个合适的时机去执行某个动作;而Intent更倾向于立即执行动作。 * pararm1:上下文 * pararm2:一般用不到,通常传入0 * pararm3:意图对象 * pararm4:指定PendingIntent的行为,有四种可选值 */PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);/** * 5.将PendingIntent设置给builder中 */builder.setContentIntent(pendingIntent);/** * 6.使用build()方法创建通知Notification对象 * ps:这里build方法提示了一个当前api最低版本比该方法所需API版本要低编译错误,所以,按AS提示加了一个@TargetApi注解 */Notification notification = builder.build();/** * 7.使用通知管理的notify()方法显示通知 * param1:自定义通知id * param2:通知对象 */manager.notify(1, notification);//取消通知,参数为通知id//manager.cancel(1);
8.2 发送接收短信
8.2.1 接收短信
接收短信主要是利用了广播机制的原理。当手机收到短信时,会发出一条值为 android.provider.Telephony.SMS_RECEIVED 的广播,这条广播里携带着短信的信息,再从中解析出短信内容即可。
主要代码:
public class MainActivity extends AppCompatActivity { public TextView sender; public TextView content; public SMSReceiver receiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sender = (TextView) findViewById(R.id.sender); content = (TextView) findViewById(R.id.content); //注册广播监听 IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); receiver = new SMSReceiver(); registerReceiver(receiver, intentFilter); } /** * 短信广播接收器类 */ class SMSReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //取出Bundle对象 Bundle bundle = intent.getExtras(); //使用 pdu 密钥来提取一个 SMS pdus 数组,其中每一个 pdu 都表示一条短信消息 Object[] pdus = (Object[]) bundle.get("pdus"); SmsMessage[] messages = new SmsMessage[pdus.length]; for (int i = 0; i < messages.length; i++) { //将每一个pdu字节数组转换为SmsMessage对象 messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]); //新的API中此方法已被下面的方法所代替 //createFromPdu(byte[] pdu, String format); } //获取发送方号码 String address = messages[0].getOriginatingAddress(); //获取短信内容 String fullMsg = ""; for (SmsMessage smsMessage : messages) { fullMsg += smsMessage.getMessageBody(); } sender.setText(address); content.setText(fullMsg); } } @Override protected void onDestroy() { super.onDestroy(); //取消广播监听 unregisterReceiver(receiver); }}
当然,读取短信也需要声明权限:
<uses-permissionandroid:name="android.permission.RECEIVE_SMS"/>
(小技巧)Android Studio模拟器模拟发送短信不同于以往的方式,是酱婶儿的:
8.2.2 拦截短信
当有短信到来时,不只自己的程序会接收短信,系统的程序也会接收短信,这样的效果会造成不好的用户体验。而收到短信后发出的广播正是一条有序广播,所以可以利用此方式来屏蔽系统短信。
两步:
(1)提高广播接收器优先级
intentFilter.setPriority(100);
(2)在onReceive方法中终止广播的继续传递
abortBroadcast();
拦截短信的功能还是要慎用,防止数据的丢失!
8.2.3 发送短信
(1)编写广播接收器,监听短信发送状态
class SMSSendReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (getResultCode() == RESULT_OK) { Toast.makeText(context, "短信发送成功", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(context, "短信发送失败", Toast.LENGTH_SHORT).show(); } }}
(2)注册广播并发送
/** * 1.注册监听短信发送状态的广播接收器 */sendFilter = new IntentFilter("SENT_SMS_ACTION");sendReceiver = new SMSSendReceiver();registerReceiver(sendReceiver, sendFilter);/** * 2.模拟点击事件发送短信 */btnSend.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //通过getDefault()方法获取到SmsManager的实例 SmsManager manager = SmsManager.getDefault(); Intent intent = new Intent("SENT_SMS_ACTION"); PendingIntent pi = PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0); /** * 发送短信 * param1:指定接收人的手机号码 * param2:null * param3:短信内容 * param4:PendingIntent对象 * param5:null */ manager.sendTextMessage(to.getText().toString(), null, msgInput.getText().toString(), pi, null); }});
不要忘记取消注册广播!
(3)注册发送短信权限:
<uses-permissionandroid:name="android.permission.SEND_SMS"/>
ps:
根据国际标准,每条短信的长度不得超过 160 个字符,如果想要发送超出这个长度的短信,则需要将这条短信分割成多条短信来发送,使用 SmsManager 的 sendMultipart-TextMessage()方法就可以实现上述功能。它的用法和 sendTextMessage()方法也基本类似。
8.3 调用摄像头和相册
8.3.1 调用摄像头
(1)修改布局文件,实现点击按钮去拍照,然后剪裁之后展示在下方的ImageView中。
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/take_photo" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Take Photo" /> <ImageView android:id="@+id/picture" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" /></LinearLayout>(2)主要代码如下:
public class MainActivity extends AppCompatActivity { public static final int TAKE_PHOTO = 1; public static final int CROP_PHOTO = 2; private Button takePhoto; private ImageView picture; private Uri imageUri; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //获取控件实例 takePhoto = (Button) findViewById(R.id.take_photo); picture = (ImageView) findViewById(R.id.picture); //给按钮注册点击事件 takePhoto.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { /** * 1.创建File对象,用于存储拍照后的图像 * Environment.getExternalStorageDirectory()获取的是SD卡根目录 */ File outputImage = new File(Environment.getExternalStorageDirectory(), "output_image.jpg"); try { //如果该文件存在,则删除后再创建 if (outputImage.exists()) { outputImage.delete(); } outputImage.createNewFile(); } catch (IOException e) { e.printStackTrace(); } /** * 2.然后调用Uri.fromFile()将File对象转换为Uri对象 * 这个Uri对象标识着output_image.jpg的唯一地址 */ imageUri = Uri.fromFile(outputImage); /** * 3.构建意图,并用putExtra方法来指定图片的输出地址,使用刚刚创建的Uri对象 * 启动相机 */ Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); //启动相机程序,这样拍的照片将会存在output_image.jpg中 startActivityForResult(intent, TAKE_PHOTO); } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { //当为拍完照的返回时 case TAKE_PHOTO: if (resultCode == RESULT_OK) { /** * 4.有结果返回时,则再次构建意图,打开剪裁程序 */ Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(imageUri, "image/*"); intent.putExtra("scale", true); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); startActivityForResult(intent, CROP_PHOTO); // 启动裁剪程序 } break; //当为剪裁完照片的返回时 case CROP_PHOTO: if (resultCode == RESULT_OK) { try { /** * 5.当剪裁完成后,通过以下方式将output_image.jpg解析为Bitmap对象 */ Bitmap bitmap = BitmapFactory.decodeStream (getContentResolver() .openInputStream(imageUri)); // 将裁剪后的照片显示出来 picture.setImageBitmap(bitmap); } catch (FileNotFoundException e) { e.printStackTrace(); } } break; default: break; } }}
(3)由于涉及到向SD卡中写入数据,所以需声明权限:
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
8.3.2 调用相册
注意:
《第一行代码》原作中调用相册的代码已过时,现已改为如下方式(下面的例子亲测可用,在4.1版本的系统和4.4版本的系统上都能正常运行。只是实际中还需对图片进行压缩处理,防止图片过大而导致内存溢出,此处无优化):
public class SecondActivity extends AppCompatActivity { //去相册选择图片请求码 private static final int CHOOSE_FROM_ALBUM = 0; //剪裁图片请求码 private static final int CROP_PHOTO = 1; private Button choosePic; private ImageView picture; private Uri imageUri; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); //获取控件 choosePic = (Button) findViewById(R.id.choose_from_album); picture = (ImageView) findViewById(R.id.picture); choosePic.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //创建File对象,用于存储选择的照片 File outputImage = new File(Environment.getExternalStorageDirectory(), "output_image.jpg"); try { //如果存在则删除 if (outputImage.exists()) { outputImage.delete(); } //创建新文件 outputImage.createNewFile(); } catch (IOException e) { e.printStackTrace(); } //将File对象转换为Uri对象 imageUri = Uri.fromFile(outputImage); /** * 去相册选择 */ Intent intent = new Intent("android.intent.action.PICK"); intent.setType("image/*"); //允许剪裁 intent.putExtra("crop", true); //允许缩放 intent.putExtra("scale", true); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); //启动 startActivityForResult(intent, CHOOSE_FROM_ALBUM); } }); } /** * 启动活动回调函数 * * @param requestCode 请求码 * @param resultCode 结果码 * @param data 回传的意图对象 */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { //选择图片成功了要启动剪裁活动 case CHOOSE_FROM_ALBUM: if (resultCode == RESULT_OK) { //判断手机系统的版本号 if (Build.VERSION.SDK_INT >= 19) { handleImageOnKitKat(data); } else { handleImageBeforeKitkat(data); } } break; //剪裁图片完成了要显示出来 case CROP_PHOTO: if (resultCode == RESULT_OK) { try { Bitmap bitmap = BitmapFactory.decodeStream (getContentResolver() .openInputStream(imageUri)); // 将裁剪后的照片显示出来(实际还需压缩图片进行优化) picture.setImageBitmap(bitmap); } catch (FileNotFoundException e) { e.printStackTrace(); } } break; default: break; } } /** * 当系统为4.4以上版本的时候,必须以以下方式才可以读取图片 * * @param data 回传的intent对象 */ @TargetApi(19) private void handleImageOnKitKat(Intent data) { String imagePath = null; Uri uri = data.getData(); imageUri = uri; if (DocumentsContract.isDocumentUri(this, uri)) { // 如果文档类型是uri,则通过document id 处理 String docId = DocumentsContract.getDocumentId(uri); if ("com.android.providers.media.documents".equals(uri .getAuthority())) { String id = docId.split(":")[1]; String selection = MediaStore.Images.Media._ID + "=" + id; imagePath = getImagePath( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection); } else if ("com.android.providers.downloads.documents".equals(uri .getAuthority())) { Uri contentUri = ContentUris.withAppendedId( Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId)); imagePath = getImagePath(contentUri, null); } } else if ("content".equalsIgnoreCase(uri.getScheme())) { // 如果不是document类型的Uri,则使用普通方式处理 imagePath = getImagePath(uri, null); } else { Toast.makeText(SecondActivity.this, "未知类型!", Toast.LENGTH_SHORT).show(); } cropImage(imagePath); } /** * 当系统为4.4以下的时候必须以以下方式读取图片 * * @param data 回传的intent对象 */ private void handleImageBeforeKitkat(Intent data) { Uri uri = data.getData(); imageUri = uri; String imagePath = getImagePath(uri, null); cropImage(imagePath); } /** * 获得选择的图片的真实路径 * * @param uri 图片的标识符 * @param selection 选择的选项,可为空 * @return 选择的图片的真实路径 */ private String getImagePath(Uri uri, String selection) { String path = null; //通过Uri跟selection来获取真实的图片路径 Cursor cursor = getContentResolver().query(uri, null, selection, null, null); if (cursor != null) { if (cursor.moveToFirst()) { path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)); } cursor.close(); } return path; } /** * 启动剪裁图片活动 * * @param imagePath 图片路径 */ private void cropImage(String imagePath) { if (imagePath != null) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(imageUri, "image/*"); intent.putExtra("scale", true); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); startActivityForResult(intent, CROP_PHOTO); } }}
8.4播放多媒体文件
8.4.1 播放音频
播放音频文件一般都是使用MediaPlayer 类来实现的,它对多种格式的音频文件提供了非常全面的控制方法。
主要代码如下:
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button play; private Button pause; private Button stop; /** * 1.创建一个MediaPlayer的实例 */ private MediaPlayer mediaPlayer = new MediaPlayer(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); play = (Button) findViewById(R.id.play); pause = (Button) findViewById(R.id.pause); stop = (Button) findViewById(R.id.stop); play.setOnClickListener(this); pause.setOnClickListener(this); stop.setOnClickListener(this); /** * 2.初始化MediaPlayer */ initMediaPlayer(); } private void initMediaPlayer() { File file = new File(Environment.getExternalStorageDirectory(), "music.mp3"); try { //指定音频文件路径 mediaPlayer.setDataSource(file.getPath()); //使MediaPlayer进入到准备状态 mediaPlayer.prepare(); } catch (IOException e) { e.printStackTrace(); } } /** * 3.执行对应操作 * * @param v */ @Override public void onClick(View v) { switch (v.getId()) { case R.id.play: if (!mediaPlayer.isPlaying()) { // 开始播放 mediaPlayer.start(); } break; case R.id.pause: if (mediaPlayer.isPlaying()) { // 暂停播放 mediaPlayer.pause(); } break; case R.id.stop: if (mediaPlayer.isPlaying()) { // 停止播放 mediaPlayer.reset(); //重新调用一遍初始化方法 initMediaPlayer(); } break; default: break; } } /** * 4.不要忘记释放资源 */ @Override protected void onDestroy() { super.onDestroy(); /** * */ if (mediaPlayer != null) { mediaPlayer.stop(); mediaPlayer.release(); } }}
8.4.2 播放视频
播放视频文件主要是通过VideoView类来实现的(实际上VideoView底层同样是利用的MediaPlayer,只不过做了很好的封装),常用方法如下:
VideoView 并不是一个万能的视频播放工具类,它在视频格式的支持以及播放效率方面都存在着较大的不足。所以,如果想要仅仅使用 VideoView就编写出一个功能非常强大的视频播放器是不太现实的。
使用VideoView类播放视频文件的步骤跟MediaPlayer类基本一致,在此略过。
0 0
- Android学习笔记(八)使用多媒体(通知、短信、摄像头、相册、音视频)
- Android视频学习(八):多媒体编程
- Android初级开发(八)——手机多媒体—通知的使用
- Android学习(15)-摄像头和相册
- Android初级开发(八)——手机多媒体—音频和视频的使用
- 学习笔记(十)运用通知和手机多媒体
- Android读书笔记(五)使用摄像头、从相册获取图片
- Android学习笔记(八) 使用菜单
- android 学习笔记 调用系统摄像头和相册
- 【Android】安卓学习笔记之调用摄像头和相册
- 软件工程视频学习笔记(八)
- 张孝祥java视频学习笔记(八)
- Android 使用摄像头和相册
- Android摄像头照相机技术-android学习之旅(八)
- Android 多媒体应用:开启摄像头、查看相册中的照片
- android多媒体部分学习笔记八------音频录制 mediaRecorder
- Android --- 多媒体应用(使用VideoView、TextureView播放视频)
- android学习笔记(八)
- 逆向mtklog
- Conway's Law
- iOS发布app到App Store教程
- FastJson
- Android studio中Module上面有红色X解决办法
- Android学习笔记(八)使用多媒体(通知、短信、摄像头、相册、音视频)
- Android BottomNavigationBar底部导航控制器的使用
- iOS中TableView的不同类型
- HDU 5023 A Corrupt Mayor's Performance Art(线段树)
- 文章标题
- 汉字的各种排序
- Ajax拿取html格式数据
- iOS 9键盘类型合集
- c#第三章升级属性MyBank