Android第一行代码学习笔记六----手机多媒体

通知

通知基本用法

静态显示
首先,调用Context的getSystemService()获取NoticationManager(),getSystemService()方法接收一个字符串参数确定获取系统的 哪个 服务 ,这 里我们 传入Context.NOTIFICATION_SERVICE 即可。
示例如下:
NotificationManager manager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
接下来创建Notification对象,构造函数接收三个参数,第一个指定通知图标,第二个指定通知ticker内容,第三个指定通知被创建的时间。示例如下:
Notification notification = new Notification(R.drawable.icon, "This is ticker text",
System.currentTimeMillis());
然后设定通知的布局。调用Notification的setLastEventInfo()方法。接收四个参数,第一个context,第二个指定标题内容,第三个指定正文,第四个暂时传入null。示例如下:
notification.setLatestEventInfo(context, "This is content title", "This is
content text", null);
此时,条用NotificationManager的notify()方法即可。接收两个参数,第一个标识id,第二个为Notification对象。示例如下
manager.notify(1, notification);
完整示例:
public class MainActivity extends Activity implements OnClickListener {
private Button sendNotice;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sendNotice = (Button) findViewById(R.id.send_notice);
sendNotice.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.send_notice:
NotificationManager manager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.
ic_launcher, "This is ticker text", System.currentTimeMillis());
notification.setLatestEventInfo(this, "This is content title",
"This is content text", null);
manager.notify(1, notification);
break;
default:
break;
}
}
通知点击响应
PendingIntent和 Intent都可以用于启动活动、启动服务以及发送广播等,区别在于Intent 更加倾向于去立即执行某个动作,而 PendingIntent 更加倾向于在某个合适的时机去执行某个动作。所以,也可以把 PendingIntent 理解为延迟执行的 Intent。
PendingIntent提供了 getActivity()方法、getBroadcast()方法、 getService()几个参数相同的静态方法来获取示例。第一个是Context,第二个通常传入0,第三个是表示意图的Intent对象,第四个确定PendingIntent行为,FLAG_ONE_SHOT、 FLAG_NO_CREATE、 FLAG_CANCEL_CURRENT 和 FLAG_UPDATE_CURRENT 这四种值。
回顾Notification的setLastestEventInfo()方法,第四个参数就是PendingIntent对象。修改前面的代码如下:
public class MainActivity extends Activity implements OnClickListener {
……
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.send_notice:
NotificationManager manager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.
ic_launcher, "This is ticker text", System.currentTimeMillis());
Intent intent = new Intent(this, NotificationActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
notification.setLatestEventInfo(this, "This is content title",
"This is content text", pi);
manager.notify(1, notification);
break;
default:
break;
}
}
}
说明:NotificationActivity是我们想要点击响应的活动,活动需要在配置文件中声明。同时,要想点击图标之后图标消失,需要在代码中对该通知进行取消,否则会一直显示,因此我们可以在响应活动中取消该通知。解决代码示例如下:
public class NotificationActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.notification_layout);
NotificationManager manager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
manager.cancel(1);
}
}

通知的高级技巧

以下高级技巧只能在实体机运行才有效果,模拟器没有以下功能。
音频
在通知来到的时候,可以设置sound属性播放一段音频。sound属性是一个uri对象。示例代码如下:
Uri soundUri = Uri.fromFile(new File("/system/media/audio/ringtones/
Basic_tone.ogg"));
notification.sound = soundUri;
振动
设置vibrate属性使手机振动。vabrate是一个长整型数组,用于设置手机静止和振动的时长,以毫秒为单位。下标偶数为静止时长,奇数为振动时长。示例代码如下:
long[] vibrates = {0, 1000, 1000, 1000};
notification.vibrate = vibrates;
控制手机要声明以下权限。
LED灯
使用 ledARGB、 ledOnMS、ledOffMS 以及 flags 这4个属性来实现这种效果。
ledARGB :控制 LED 灯颜色,一般有红绿蓝三种颜色可选。
ledOnMS :指定 LED 灯亮起的时长,以毫秒为单位。
ledOffMS:用于指定 LED 灯暗去的时长,以毫秒为单位。
flags :用于指定通知的一些行为,包括显示 LED 灯这一选项。
示例代码:
notification.ledARGB = Color.GREEN;
notification.ledOnMS = 1000;
notification.ledOffMS = 1000;
notification.flags = Notification.FLAG_SHOW_LIGHTS;
默认效果
默认效果会根据当前手机环境决定播放的铃声以及振动方式,示代码如下:
notification.defaults = Notification.DEFAULT_ALL;

接收和发送短信

接收短信

当手机接收到一条短信的时候,系统会发出一条值为 android.provider.Telephony.SMS_RECEIVED 的广播,这条广播里携带着与短信相关的所有数据。我们的应用程序可以监听此广播然后解析内容即可。在主类中建立MessageReceiver内部类,示例如下:
public class MainActivity extends Activity {
……
class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
Object[] pdus = (Object[]) bundle.get("pdus"); // 提取短信消息
SmsMessage[] messages = new SmsMessage[pdus.length];
for (int i = 0; i < messages.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
}
String address = messages[0].getOriginatingAddress(); // 获取发
送方号码
String fullMessage = "";
for (SmsMessage message : messages) {
fullMessage += message.getMessageBody(); // 获取短信内容
}
sender.setText(address);
content.setText(fullMessage);
}
}
}
从 Intent 参数中取出了一个 Bundle 对象,然后使用 pdu 密钥来提取一个 SMS pdus 数组,其中每一个 pdu 都表示一条短信消息。接着使用 SmsMessage 的createFromPdu()方法将每一个 pdu 字节数组转换为 SmsMessage 对象,调用这个对象的getOriginatingAddress()方法就可以获取到短信的发送方号码,调用 getMessageBody()方法就可以获取到短信的内容,然后将每一个 SmsMessage 对象中的短信内容拼接起来,就组成了一条完整的短信。
此时,还需要注册MessageReceiver,代码如下:
public class MainActivity extends Activity {
private TextView sender;
private TextView content;
private IntentFilter receiveFilter;
private MessageReceiver messageReceiver;
@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);
receiveFilter = new IntentFilter();
receiveFilter.addAction("android.provider.Telephony.SMS_RECEIVED");
messageReceiver = new MessageReceiver();
registerReceiver(messageReceiver, receiveFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(messageReceiver);
}
……
}
说明:我们使用的是动态注册技术,因此还需要在onDestroy()方法中取消注册。此外,还需要声明接收短信的权限,声明如下:

拦截短信

短信广播是一条有序广播。因此是可以截断的,代码如下:
public class MainActivity extends Activity {
……
@Override
protected void onCreate(Bundle savedInstanceState) {
……
receiveFilter = new IntentFilter();
receiveFilter.addAction("android.provider.Telephony.SMS_RECEIVED");
receiveFilter.setPriority(100);
messageReceiver = new MessageReceiver();
registerReceiver(messageReceiver, receiveFilter);
}
……
class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
……
abortBroadcast();
}
}
}
说明:代码主要有两步,一是提高MessageReceiver优先级,二是在onReceive()方法中调用abortBroadcast()。

发送短信

我们直接来看如下示例代码:
public class MainActivity extends Activity {
……
private EditText to;
private EditText msgInput;
private Button send;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
……
to = (EditText) findViewById(R.id.to);
msgInput = (EditText) findViewById(R.id.msg_input);
send = (Button) findViewById(R.id.send);
send.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(to.getText().toString(), null,
msgInput.getText().toString(), null, null);
}
});
}
……
}
说明:to控件表示发送给谁,msgInput表示发送的内容,send表示发送按钮。一旦按钮被点击,则调用SmsManager的getDefault()方法获取实例,然后调用实例的sendTextMessage()方法发送短信。该方法接收5个参数,1指定号码,3指定短信内容,其他暂时传入null。
发送短信也需要声明权限,声明如下:
如果需要查看短信是否发送成功,则可以利用sendTextMessage的第四个参数进行监控。修改主类代码如下:
public class MainActivity extends Activity {
……
private IntentFilter sendFilter;
private SendStatusReceiver sendStatusReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
……
sendFilter = new IntentFilter();
sendFilter.addAction("SENT_SMS_ACTION");
sendStatusReceiver = new SendStatusReceiver();
registerReceiver(sendStatusReceiver, sendFilter);
send.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SmsManager smsManager = SmsManager.getDefault();
Intent sentIntent = new Intent("SENT_SMS_ACTION");
PendingIntent pi = PendingIntent.getBroadcast
(MainActivity.this, 0, sentIntent, 0);
smsManager.sendTextMessage(to.getText().toString(), null,
msgInput.getText().toString(), pi, null);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(messageReceiver);
unregisterReceiver(sendStatusReceiver);
}
……
class SendStatusReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (getResultCode() == RESULT_OK) {
// 短信发送成功
Toast.makeText(context, "Send succeeded",
Toast.LENGTH_LONG).show();
} else {
// 短信发送失败
Toast.makeText(context, "Send failed",
Toast.LENGTH_LONG).show();
}
}
}
}
说明:将PendingIntent对象作为sendTextMessage的第四个参数,注册广播接收器SendStatusReceive。广播接收器监听短信发送状态。同时,国际标准规定每条短信长度不得超过160个字符,如果超出则需要分条发送。可以利用sendMultipart-TextMessage()方法实现该功能。

调用摄像头和相册

调用摄像头拍照

首先新建项目,activity_main.xml代码如下:

说明:控件button用于拍照,imageview用于显示照片。
主类代码示例如下:
public class MainActivity extends Activity {
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 OnClickListener() {
@Override
public void onClick(View v) {
// 创建File对象,用于存储拍照后的图片
File outputImage = new File(Environment.
getExternalStorageDirectory(), "tempImage.jpg");
try {
if (outputImage.exists()) {
outputImage.delete();
}
outputImage.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
imageUri = Uri.fromFile(outputImage);
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:
if (resultCode == RESULT_OK) {
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 {
Bitmap bitmap = BitmapFactory.decodeStream
(getContentResolver()
.openInputStream(imageUri));
picture.setImageBitmap(bitmap); // 将裁剪后的照片显示出来
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
break;
default:
break;
}
}
}
说明:点击拍照按钮后,首先创建 File对象,存储用摄像头拍下的照片,命名为output_image.jpg,调用Environment的getExternalStorageDirectory()方法获取到手机SD卡的根目录,将照片存储在根目录下。接着调用Uri的fromFile()方法将File对象转换成Uri对象,标识这个图片的唯一地址。接着构建出一个 Intent对象, 并将这个 Intent的 action指定为android.media.action.IMAGE_CAPTURE,再调用Intent的putExtra()方法指定图片的输出地址。这里设置为刚刚得到的Uri对象,最后调用startActivityForResult()来启动活动。在该示例中,使用的隐式intent,系统会启动能够响应这个Intent的照相机程序,拍下的照片会输出到output_image.jpg中。
我们使用的是startActivityForResult启动活动,因此拍完照会有结果返回到onActivityResult()方法中,如果发现拍照成功,则会再次构建Intent对象,并把它的 action 指定为 com.android.camera.action.CROP。这个 Intent 是用于对拍出的照片进行裁剪的,给这个Intent 设置上一些必要的属性,并再次调用 startActivityForResult()来启动裁剪程序。裁剪后的照片同样会输出到 output_image.jpg 中。
裁剪操作完成之后,程序又会回调到 onActivityResult()方法,我们调用 BitmapFactory 的 decodeStream()方法将 output_image.jpg 这张照片解析成 Bitmap 对象,然后把它设置到 ImageView 中显示出来。
示例涉及到向SD卡写数据,因此需要权限声明,声明如下:
此时,就可以拍照并剪裁然后显示照片了。

从相册选择照片

从前面的代码基础修改activity_main.xml文件

MainActivity加入选择相册照片代码如下:
public class MainActivity extends Activity {
……
private Button chooseFromAlbum;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
……
chooseFromAlbum = (Button) findViewById(R.id.choose_from_album);
chooseFromAlbum.setOnClickListener(new 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();
}
imageUri = Uri.fromFile(outputImage);
Intent intent = new Intent("android.intent.action.
GET_CONTENT");
intent.setType("image/*");
intent.putExtra("crop", true);
intent.putExtra("scale", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, CROP_PHOTO);
}
});
}
……
}
说明:创建了一个 File 对象,用于存储从相册中选择的图片。构建出一个 Intent 对象,并将它的 action 指定为android.intent.action.GET_CONTENT。接着给这个 Intent 对象设置一些必要的参数,包括是否允许缩放和裁剪、图片的输出位置等。最后调用 startActivityForResult()方法,就可以打开相册程序选择照片了。
如果照片过大,本程序可能会崩溃。解决办法是根据需求先对照片进行压缩再加载到内存中。

播放多媒体文件

播放音频

Android 中播放音频文件一般都是使用 MediaPlayer 类来实现,一些常用控制方法如下所示。
Android第一行代码学习笔记六----手机多媒体_第1张图片
具体流程是:首先创建一个MediaPlayer对象,然后调用setDataSource设置音频文件路径,再调用prepare()使MediaPlayer进入到准备状态,接下来就可以调用start播放音频,pause()暂停播放,reset停止播放。
MainActivity示例代码如下:
public class MainActivity extends Activity implements OnClickListener {
private Button play;
private Button pause;
private Button stop;
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);
initMediaPlayer(); // 初始化MediaPlayer
}
private void initMediaPlayer() {
try {
File file = new File(Environment.getExternalStorageDirectory(),
"music.mp3");
mediaPlayer.setDataSource(file.getPath()); // 指定音频文件的路径
mediaPlayer.prepare(); // 让MediaPlayer进入到准备状态
} catch (Exception e) {
e.printStackTrace();
}
}
@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;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
}
}
}
说明:在onDestroy()方法中,我们需要分别调用stop()和release()方法将与MediaPlayer相关的资源释放掉。

播放视频

播放视频利用VideoView类实现。常用方法如下:
Android第一行代码学习笔记六----手机多媒体_第2张图片
activity_main示例代码:



说明:首先有一个Video View来显示视频,同时有三个按钮,控制播放,暂停和重新播放。
MainActivity示例代码如下:
public class MainActivity extends Activity implements OnClickListener {
private VideoView videoView;
private Button play;
private Button pause;
private Button replay;
@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);
replay = (Button) findViewById(R.id.replay);
videoView = (VideoView) findViewById(R.id.video_view);
play.setOnClickListener(this);
pause.setOnClickListener(this);
replay.setOnClickListener(this);
initVideoPath();
}
private void initVideoPath() {
File file = new File(Environment.getExternalStorageDirectory(),
"movie.3gp");
videoView.setVideoPath(file.getPath()); // 指定视频文件的路径
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.play:
if (!videoView.isPlaying()) {
videoView.start(); // 开始播放
}
break;
case R.id.pause:
if (videoView.isPlaying()) {
videoView.pause(); // 暂时播放
}
break;
case R.id.replay:
if (videoView.isPlaying()) {
videoView.resume(); // 重新播放
}
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (videoView != null) {
videoView.suspend();
}
}
}
说明:调用initVideoPath()来设置视频文件的路径。在onDestory()中,需要调用suspend()方法释放VideoView所占用的资源。同时需要注意,VideoView不是一个万能视频播放工具类,在格式的支持以及播放效率方面都存在较大不足。






































你可能感兴趣的:(android)