安卓运用手机多媒体
Posted 要加油
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安卓运用手机多媒体相关的知识,希望对你有一定的参考价值。
一.连接真机
第一步:手机下载一个360手机助手,电脑下载一个360安全卫士,电脑下载后在360安全卫士的软件管家里下载360手机助手(电脑必须要先下载360安全卫士才能用360手机助手,单独下360手机助手是不行的)。书上说豌豆荚也可以,我试过了连接不上,不知道什么原因。
第二步:下载完360手机助手后,用数据线连接手机与电脑,手机打开 开发者选项与usb调试,我是一加手机,打开步骤:
https://jingyan.baidu.com/article/67508eb47b824a9cca1ce48b.html
第三步:然后电脑打开360手机助手,会叫你用手机的360手机助手去扫码连接的(网络一定要够好,不然会连接失败的),显示以下的图就是连接成功了:
现在来测试一下吧,新建一个Hello项目。运行项目后,你的手机会相当于模拟器一样安装Hello软件。
二、使用通知
通知是android中比较由特色的一个功能,当某个应用程序需要向用户发出一些提示信息时,而该程序由不在前台的显示,就可以借助通知来实现。
步骤:
首先要判断你的安卓API是多少,我们需要通过判断当前设备的API来针对性的进行发送通知栏。因为API26(Android 8.0)以后,引入了**通知渠道(Notification Channels)**这么一个东西来帮助用户管理通知。
if (Build.VERSION.SDK_INT >= 26) { //这里是API26以上的方法 } else { //这里是API26以下的方法 }
然后根据API的大小去写代码
API>=26:
if (Build.VERSION.SDK_INT >= 26) { NotificationChannel mChannel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_LOW);//NotificationManager对象调用一下createNotificationChannel()方法并传入NotificationChannel对象 notificationManager.createNotificationChannel(mChannel); notification = new Notification.Builder(this,id) .setChannelId(id) .setContentTitle("title") .setContentText("This is content text") .setSmallIcon(R.drawable.send) .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ff)) .build(); }
代码的解释:
1.一个NotificationManager来对通知进行管理,可以调用Context的getSystemService()方法获取到,getSystemService()方法接受一个字符串参数用于确定获取系统的哪一个服务,这里传入Context.NOTIFICATION_SERVICE即可
2.NotificationChannel的三个参数
id:通知渠道的 ID ,用户不可见,实例化Notification的时候需要用到,如果这个 ID 在实例化Notification的时候没有对应上,通知栏无效,系统还会Toast弹出一个错误*(软件不会闪退)*
name:这个是便于用户管理通知用的,用户可见
Importance:渠道优先级
3.setContentTittle:用于指定指定通知标题的内容,下拉系统状态栏就可以看到这部分内容
setContentText:指定统治的正文的上下文
setWhen:指定通知被创建的时间
setSmallIcon:设置通知的小图标
setLargeIcon:设置通知的大图标,当系统下拉时能可以看到设置的大图标
API<26
notification = new Notification.Builder(this) .setContentTitle("title") .setContentText("This is content text") .setSmallIcon(R.drawable.send) .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ff)) .build();
完整的代码:
MainActivity.java代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button send=(Button)findViewById(R.id.send_button); send.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.send_button: String id = "my_channel_01"; String name="panq"; NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); Notification notification = null; //Notification在android 8.0以上设置时,需要设置渠道信息才能够正常显示通知。 if (Build.VERSION.SDK_INT >= 26) {//判断API,API26以上的方法 /*NotificationChannel的三个参数 id:通知渠道的 ID ,用户不可见,实例化Notification的时候需要用到, 如果这个 ID 在实例化Notification的时候没有对应上,通知栏无效,系统还会Toast弹出一个错误*(软件不会闪退)* name:这个是便于用户管理通知用的,用户可见 Importance:渠道优先级 */ NotificationChannel mChannel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_LOW); //NotificationManager对象调用一下createNotificationChannel()方法并传入NotificationChannel对象 notificationManager.createNotificationChannel(mChannel); notification = new Notification.Builder(this,id) .setChannelId(id) .setContentTitle("title") .setContentText("This is content text") .setSmallIcon(R.drawable.send) .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ff)) .build(); } else {//API26以下的方法 notification = new Notification.Builder(this) .setContentTitle("title") .setContentText("This is content text") .setSmallIcon(R.drawable.send) .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ff)) .build(); } notificationManager.notify(111123, notification); break; default: break; } } }
activity_main.xml:只定义了一个发送消息的按钮,当点击按钮时,会发送消息
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/send_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="发送通知"/> </LinearLayout>
运行程序,点击按钮:
此时的这个是没有点击效果的,也没有反应,如果要实现点击的设置需要涉及到:PendingIntent
PendingIntent可以简单地理解为延迟执行的Intent。
PendingInternet的用法:
提供了几个静态方法用于获取PendingInternet的实例,可以根据选择使用getActivity()方法、getBroadcast()方法、getService()方法
这几个方法有四个参数,参数都是相同的:
第一个参数:content
第二个参数:一般传入0
第三个参数:Intent对象,可以通过这个对象构建出pendingInternet,这里就可以通过构造出的一个延迟执行的意图,当用户点击时就可以跳转到该逻辑
第四个参数:用于确定PendingInternet的行为,FLAG_ONE_SHOT、FLAG_NO_CREATE、FLAG_CANCEL_CURRENT、FLAG_UPDATE_CURRENT,通常情况下传入0
NotificationCompat.Buolder这个构造器中还可以连缀一个setContentIntent()方法,接受的参数是一个PendingIntent对象
此时新建一个NotificationActivity活动:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="This is Notification Activity." android:gravity="center"/> </LinearLayout>
修改MainActivity.java代码(红色的代码是新增上去的)
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button send=(Button)findViewById(R.id.send_button); send.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.send_button: Intent intent=new Intent(MainActivity.this,NotificationActivity.class); PendingIntent pendingIntent=PendingIntent.getActivity(this,0,intent,0); String id = "my_channel_01"; String name="panq"; NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); Notification notification = null; //Notification在android 8.0以上设置时,需要设置渠道信息才能够正常显示通知。 if (Build.VERSION.SDK_INT >= 26) {//判断API,API26以上的方法 NotificationChannel mChannel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_LOW); notificationManager.createNotificationChannel(mChannel); notification = new Notification.Builder(this,id) .setChannelId(id) .setContentTitle("title") .setContentText("This is content text") .setSmallIcon(R.drawable.send) .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ff)) .setContentIntent(pendingIntent) .setAutoCancel(true)//点击通知后会消失在显示栏 .build(); } else {//API26以下的方法 notification = new Notification.Builder(this) .setContentTitle("title") .setContentText("This is content text") .setSmallIcon(R.drawable.send) .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ff)) .setContentIntent(pendingIntent) .setAutoCancel(true)//点击通知后会消失在显示栏 .build(); } notificationManager.notify(111123, notification); break; default: break; } } }
运行程序,点击通知后。跳转到另一个活动:
三、通知的进阶技巧
1、setSound():该方法可以在接收通知的时候发送一段音频,能够更好的告知用户通知的到来。接收一个Uri参数,所以在指定音频文件的时候还需要首先获取到音频文件对应的Uri。
2、setvibrate():该方法在接收通知的时候让手机震动,参数是一个数组,用于设置手机震动的时长,以毫秒为单位。
它是一个长整型的数组,用于设置手机静止和振动的时长,以毫秒为单位。下标为0的值 表示手机静止的时长,下标为1的值表示手机振动的时长,下标为2的值又表示手机静止的时 长,以此类推。所以,如果想要让手机在通知到来的时候立刻振动1秒,然后静止1秒,再振动1秒,代码就可以写成:
setVibrate(new long[]{0,1000,1000,1000})
想要手机震动还需要申请权限:<uses-permission android:name="android.permission.VIBRATE"/>
3、setLights():该方法用于设置收到消息时手机发出led光,接收三个参数:①LED灯的颜色指定;②LED灯亮的时长;③执行LED灯暗去的时长(以毫秒为单位)
4、setDefaults(NotificationCompat.DEFAULT_ALL):当你不想进行那么多繁杂的设置,也可以直接使用通知的默认效果,它会根据当前手 机的环境来决定播放什么铃声,以及如何振动
5、setStyle():该方法允许构建出富文本的通知内容。也就是说通知中不光可以有文字和图标,还可以包含更多的东西文本通知内容。setStyle() 方法接收一 个NotificationCompat.Style 参数,这个参数就是用来构建具体的富文本信息的,如长文 字、图片等。
当文字内容较多使用:setStyle(new NotificationCompat.BigTextStyle().bigText(" ........")
同时还可以设置图片进行方法:new NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(getResources() , R.drawable.big_image))
四、悬挂式通知
android 通知的四种形式: 普通通知 悬挂式通知 折叠式通知 锁屏通知。
推荐看一下:https://www.jianshu.com/p/8cec293cfa9a,以及郭霖对android 8.0系统的通知栏适配
直接上代码:
MainActivity.java:
public class MainActivity extends AppCompatActivity { private NotificationChannel channel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { String channelId = "chat"; String channelName = "聊天消息"; int importance = NotificationManager.IMPORTANCE_HIGH; createNotificationChannel(channelId, channelName, importance); } } public void sendChatMsg(View view) { Intent intent=new Intent(MainActivity.this,NotificationActivity.class); PendingIntent pendingIntent=PendingIntent.getActivity(this,0,intent,0); NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); //如果聊天消息该渠道被关闭了,这里我们判断如果通知渠道的importance等于IMPORTANCE_NONE,就说明用户将该渠道的通知给关闭了,这时会跳转到通知的设置界面提醒用户手动打开。 if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) { Intent intent1 = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS); intent1.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName()); intent1.putExtra(Settings.EXTRA_CHANNEL_ID, channel.getId()); startActivity(intent1); Toast.makeText(this, "请手动将通知打开", Toast.LENGTH_SHORT).show(); } Notification notification = new NotificationCompat.Builder(this, "chat") .setContentTitle("收到一条聊天消息") .setContentText("今天中午吃什么?") .setContentIntent(pendingIntent) .setWhen(System.currentTimeMillis())//设置时间 .setSmallIcon(R.drawable.send) .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ff)) .setAutoCancel(true)//点击通知后会消失在显示栏 .setVibrate(new long[]{0,1000,1000,1000})//设置震动 .setNumber(1)//未读消息的数量 .setFullScreenIntent(pendingIntent,true)
.setDefaults(0)
.setPriority(NotificationCompat.PRIORITY_MAX) .build(); manager.notify(1, notification); } /** *创建通知渠道 * @param channelId 通知渠道的id * @param channelName 通知渠道的名字 * @param importance 渠道优先级 */ private void createNotificationChannel(String channelId, String channelName, int importance) { channel = new NotificationChannel(channelId, channelName, importance); channel.setShowBadge(true);//允许这个渠道下的通知显示角标 NotificationManager notificationManager = (NotificationManager) getSystemService( NOTIFICATION_SERVICE); notificationManager.createNotificationChannel(channel); } }
如果你要想弹出消息后自动消失,就必须要加这两句:
.setDefaults(0)
.setPriority(NotificationCompat.PRIORITY_MAX)
activity_main.xml文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/send_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="发送通知" android:onClick="sendChatMsg"/> </LinearLayout>
注意:使用NotificationChannel要保证你的minSdkVersion要在26以上,如果低于26可以自己改,去app--build-gradle改,低于26会出现错误:
运行程序,点击发送信息按钮,会弹出一条信息,弹出过几秒会消失,通知栏上通知还在。
五、调用摄像头与相册
1.摄像头的调用
这里直接进入主题,给出使用步骤:
第一步:创建一个存储照片的文件
第二步:根据这个文件,创建一个指向该文件的Uri对象实例
第三步:创建一个意图Intent,通过系统Action : android.media.action.IMAGE_CAPTURE初始化并通过putExtra()向意图中存入第二步获取的Uri对象实例
第四步:通过startActivityForResult()打开相机
第五步:在onActivityResult()中实现把相机拍摄照片保存到Intent中的Uri实例对象指向文件里即可
2.获取手机相册
直接进入主题,给出使用步骤:
第一步:创建一个意图,通过设置系统Action为:android.intent.action.GET_CONTENT 用于打开手机资源,并通过setType(“image/*”)来限定只查看图片资源。
第二步:根据打开资源的路径创建指向对应路径的Uri实例对象
第三步:获取选择图片路径(难点)
第四步:显示图片
详细的解释可以看这个:https://blog.csdn.net/hyperprogram/article/details/70284539
示例代码:
(1)activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="拍照上传" android:onClick="takePhoto"/> <Button android:id="@+id/chose_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="从相册中选择" android:onClick="choosePhoto" /> <ImageView android:id="@+id/picture" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center"/> </LinearLayout>
(2)MainActivity.java(其实都是跟着《第一行代码》打的)
1 public class MainActivity extends AppCompatActivity { 2 private Uri imageUri; 3 private ImageView picture1;// = (ImageView) findViewById(R.id.picture); 4 public static final int TAKE_PHOTO = 1; 5 public static final int CHOOSE_PHOTO = 2; 6 7 @Override 8 protected void onCreate(Bundle savedInstanceState) { 9 super.onCreate(savedInstanceState); 10 setContentView(R.layout.activity_main); 11 picture1 = (ImageView) findViewById(R.id.picture); 12 } 13 //从相册中选择照片 14 public void choosePhoto(View view){ 15 if(ContextCompat.checkSelfPermission(MainActivity.this, 16 Manifest.permission.WRITE_EXTERNAL_STORAGE)!=PackageManager.PERMISSION_GRANTED){//若没有权限就申请权限 17 ActivityCompat.requestPermissions(MainActivity.this,new 18 String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1); 19 }else{ 20 openAlbum(); 21 } 22 } 23 24 private void openAlbum() { 25 Intent intent=new Intent("android.intent.action.PICK"); 26 intent.setType("image/*"); 27 startActivityForResult(intent,CHOOSE_PHOTO); 28 } 29 30 //拍照 31 public void takePhoto(View view){ 32 //创建File对象,用于存储拍照后的图片 33 File outputImage = new File(getExternalCacheDir(),"output_image.jpg"); 34 35 try { 36 if (outputImage.exists()){//文件存在就删除 37 outputImage.delete(); 38 } 39 outputImage.createNewFile();//文件不存在就创新 40 }catch (Exception e){ 41 e.printStackTrace(); 42 } 43 44 if (Build.VERSION.SDK_INT >=24){//android版本7.0以上 45 //将File对象装换为Uri对象 46 imageUri = FileProvider.getUriForFile(MainActivity.this,"com.example.cameraalbumtest",outputImage); 47 }else {//android版本7.0以下 48 //将File对象装换为Uri对象 49 imageUri = Uri.fromFile(outputImage); 50 } 51 //启动相机 52 Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); 53 intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);//指定输出地址 54 startActivityForResult(intent,TAKE_PHOTO);//startActivityForResult(Intent intent, int requestCode),第一个参数是intent,第二个是请求码 55 } 56 57 /** 58 *启动其他界面并返回数据。拍照完或选择完相册会调用此方法 59 * @param requestCode 请求码,对应startActivityForResult(Intent intent, int requestCode)的requestCode 60 * @param resultCode 返回码,通过该参数判断子activity返回的状态,有OK,CANCELED,RESULT_FIRST_USER等, 61 * @param data 用来传递数据,对应子Activity的一个实例变量Intent mResultData,初始化为null,可通过setResult(int resultCode, Intent data)修改。 62 */ 63 @Override 64 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 65 super.onActivityResult(requestCode, resultCode, data); 66 switch (requestCode) { 67 case TAKE_PHOTO: 68 if (resultCode == RESULT_OK) { 69 try { 70 //显示照片 71 Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri)); 72 picture1.setImageBitmap(bitmap); 73 } catch (Exception e) { 74 e.printStackTrace(); 75 } 76 } 77 break; 78 case CHOOSE_PHOTO: 79 if(resultCode==RESULT_OK){ 80 //判断手机版本号 81 if(Build.VERSION.SDK_INT>=19){ 82 //4.4及以上系统使用这个方法处理图片 83 handleImageOnKitKat(data); 84 }else { 85 handleImageBeforeKitKat(data); 86 } 87 } 88 break; 89 default: 90 break; 91 } 92 } 93 //手机系统版本大于4.4 94 @TargetApi(19) 95 private void handleImageOnKitKat(Intent data){ 96 String imagePath=null; 97 Uri uri=data.getData(); 98 if(DocumentsContract.isDocumentUri(this,uri)){ 99 //document类型的Uri处理方式 100 String docId=DocumentsContract.getDocumentId(uri); 101 if("com.android.providers.media.documents".equals(uri.getAuthority())){ 102 String id=docId.split(":")[1]; 103 String seletion=MediaStore.Images.Media._ID+"="+id; 104 imagePath=getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,seletion); 105 }else if("com.android.providers.downloads.documents".equals(uri.getAuthority())){ 106 Uri contentUri= ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"),Long.valueOf(docId)); 107 imagePath=getImagePath(contentUri,null); 108 } 109 }else if("content".equalsIgnoreCase(uri.getScheme())){ 110 //content类型的Uri处理方式 111 imagePath=getImagePath(uri,null); 112 }else if("file".equalsIgnoreCase(uri.getScheme())){ 113 //file类型的Uri,直接获取路径即可 114 imagePath=uri.getPath(); 115 } 116 Log.i("MainActivity",imagePath); 117 displayImage(imagePath); 118 } 119 //ApI<19 120 private void handleImageBeforeKitKat(Intent data){ 121 Uri uri=data.getData(); 122 String imagePath=getImagePath(uri,以上是关于安卓运用手机多媒体的主要内容,如果未能解决你的问题,请参考以下文章