import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.text.TextPaint;
import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat; import com.google.android.cameraview.CameraView; import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID; public class Ruzhu_Index_Activity extends AppCompatActivity implements Screensaver.OnTimeOutListener, View.OnClickListener {
private ImageButton imgbtn;
private ImageButton btnMenling;
private ImageButton dasao;
private ImageButton darao;
private LinearLayout text_menpai;
private TextView text_damenpai;
private ImageButton weixin;
private Screensaver mScreensaver;
private LinearLayout line_img_menling;
private LinearLayout line_text_menling;
private LinearLayout line_text_qingwudarao;
private LinearLayout linea_yingcangrenlian;
private LinearLayout linea_menpai;
int i;
//播放铃声
private Ringtone r; //视频插件
private static final String TAG = "MainActivity";
private static final int REQUEST_CAMERA_PERMISSION = 1;
private CameraView mCameraView;
//用于在子线程中处理图片数据
private Handler mBackgroundHandler;
//后置摄像头
private int mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
//前置摄像头
private int cameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
private static final int COMPLETED = 0;
//多线程调用
private Handler handler=new Handler(){
@SuppressLint("WrongConstant")
@Override
public void handleMessage(@NonNull Message msg) {
if (msg.what == COMPLETED) {
int num = btnMenling.getTextAlignment();
System.out.println(num);
if (num == 1) {
btnMenling.setBackground(getResources().getDrawable(R.drawable.btn1));
btnMenling.setTextAlignment(2);
} else {
btnMenling.setBackground(getResources().getDrawable(R.drawable.btn_doorbell_bell_unsel));
btnMenling.setTextAlignment(1);
}
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ruzhuindex);
//初始化控件
init();
//按钮单击事件
btn();
//添加相机监听回调
if (mCameraView != null) {
mCameraView.addCallback(mCallback);
}
//捕获屏幕状况
mScreensaver = new Screensaver(10000); //定时5秒
mScreensaver.setOnTimeOutListener(this); //监听
mScreensaver.start(); //开始计时
//门铃点击
butn_menling();
//size字体加粗
textsizi();
//隐藏标题栏
if (getSupportActionBar() != null) {
getSupportActionBar().hide();
}
//透明状态栏
setStatusBarFullTransparent();
}
//单击事件
private void btn() {
//单击事件
imgbtn.setOnClickListener(this);
darao.setOnClickListener(this);
btnMenling.setOnClickListener(this);
dasao.setOnClickListener(this);
text_damenpai.setOnClickListener(this);
} //初始化控件
private void init() {
//相机
mCameraView =findViewById(R.id.camera);
//隐藏的菜单其他功能
darao=findViewById(R.id.darao);
line_text_qingwudarao=findViewById(R.id.line_text_qingwudarao);
dasao=findViewById(R.id.dasao);
weixin=findViewById(R.id.weixin);
//门铃
line_img_menling=findViewById(R.id.line_img_menling);
btnMenling=findViewById(R.id.btn_menlin);
line_text_menling=findViewById(R.id.line_text_menling);
//菜单
imgbtn =findViewById(R.id.imgbut);
//门牌号码
text_damenpai=findViewById(R.id.text_damenpai);
linea_menpai=findViewById(R.id.linea_menpai);
text_menpai=findViewById(R.id.text_menpai);
text_menpai=findViewById(R.id.text_menpai);
//人脸框
linea_yingcangrenlian=findViewById(R.id.linea_yingcangrenlian);
} //点击门铃事件效果
private void butn_menling(){
btnMenling.setOnClickListener(mOnClickListener);
} //拍照的点击事件
@SuppressLint("WrongConstant")
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_menlin:
//播放铃声
defaule(getApplicationContext());
//唤醒相机
if (!mCameraView.isCameraOpened()){
//启动前置摄像头
mCameraView.setFacing(cameraId);
mCameraView.start();
}
//延迟1秒拍照
new Handler().postDelayed(new Runnable(){
public void run() {
//拍照
if (mCameraView!=null){
mCameraView.takePicture();
}
}
}, 1000); text_damenpai.setVisibility(View.GONE);
text_menpai.setVisibility(View.VISIBLE);
linea_yingcangrenlian.setVisibility(View.VISIBLE);
linea_menpai.setVisibility(View.GONE);
btnMenling.setBackground(getResources().getDrawable(R.drawable.btn1));
final Timer t = new Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
int num = btnMenling.getTextAlignment();
Message msg = new Message();
msg.what = COMPLETED;
handler.sendMessage(msg);
if (i>2&&num==2){
i=0;
t.cancel();
}
i++;
}
},0,1000);
break;
}
}
};
//播放铃声
private void defaule(Context context){
if (r==null){
Log.e("----初始化铃声-----",getApplicationContext()+"");
String uri = "android.resource://" + context.getPackageName() + "/" + R.raw.dingdong;
Uri no = Uri.parse(uri);
r = RingtoneManager.getRingtone(context.getApplicationContext(), no);
}
if (!r.isPlaying()){
Log.e("--------播放铃声-----" ,getApplicationContext()+"");
r.play(); }
} /**
* 动态获取摄像机权限和存储权限
*/
@SuppressLint("WrongConstant")
protected void onResume() {
super.onResume();
//检查权限,如果有权限就启动相机,没有就去请求权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED) { } else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},
REQUEST_CAMERA_PERMISSION);
}
//获取存储权限
if (Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
}
}
/**
* 关闭相机
*/
protected void onPause() {
//关闭相机,释放相机
mCameraView.stop();
Log.e("**onPause()**","释放相机");
super.onPause();
}
//运行时请求权限
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_CAMERA_PERMISSION:
if (permissions.length != 1 || grantResults.length != 1) {
throw new RuntimeException("Error on requesting camera permission.");
}
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "grantResults[0]", Toast.LENGTH_SHORT).show();
}
break;
}
}
//在子线程保存图片
private Handler getBackgroundHandler(){
if (mBackgroundHandler==null){
HandlerThread thread=new HandlerThread("background");
thread.start();
mBackgroundHandler=new Handler(thread.getLooper());
}
return mBackgroundHandler;
}
//相机 监听回调事件
private CameraView.Callback mCallback = new CameraView.Callback() {
@Override
public void onCameraOpened(CameraView cameraView) {
Log.d(TAG, "打开相机");
} @Override
public void onCameraClosed(CameraView cameraView) {
mCameraView.stop();
Log.d(TAG, "退出相机");
} @Override
public void onPictureTaken(CameraView cameraView, final byte[] data) {
Log.d(TAG, "***onPictureTaken***" + data.length);
Toast.makeText(cameraView.getContext(), "**拍照**", Toast.LENGTH_SHORT).show();
getBackgroundHandler().post(new Runnable() {
@Override
public void run() {
//在子线程中保存图片
try {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Log.d("***初始化长度****", String.valueOf(data.length)); Log.i("wechat", "压缩前图片的大小" + (bitmap.getByteCount() / 1024 / 1024)
+ "M宽度为" + bitmap.getWidth() + "高度为" + bitmap.getHeight());
               //照片文件存在手机DCIM/文件夹下
                        String fileName = "/sdcard/DCIM/" + UUID.randomUUID() + ".jpg";
FileOutputStream outputStream = new FileOutputStream(fileName);
outputStream.write(data);
//判断目录是否可用
File file = new File(fileName);//创建文件
if (!file.getParentFile().exists()) {
file.getParentFile().mkdir();//创建文件夹
}
//图片的路径
String fa = file.getAbsolutePath();
//根据生成的图片路径,重新压缩,并存入内存
compress(fa);
//删除文件
deleteSingleFile(fa);
//bitmap释放
bitmap.recycle();
bitmap = null;
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "拍照失败!" + e.toString(), Toast.LENGTH_LONG).show();
Log.d("错误信息:", e.toString());
e.printStackTrace();
}
}
});
}
}; /**
* 压缩图片的方法,根据个人情况而定。需要压缩则调用该方法
* @param srcPath 根据路径读取
*/
public void compress(String srcPath) {
final String fileName = "/sdcard/DCIM/" + UUID.randomUUID() + ".jpg";
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
float hh = dm.heightPixels;
float ww = dm.widthPixels;
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeFile(srcPath, opts);
opts.inJustDecodeBounds = false;
int w = opts.outWidth;
int h = opts.outHeight;
int size = 0;
if (w <= ww && h <= hh) {
size = 1;
} else {
double scale = w >= h ? w / ww : h / hh;
double log = Math.log(scale) / Math.log(2);
double logCeil = Math.ceil(log);
size = (int) Math.pow(2, logCeil);
}
opts.inSampleSize = size;
bitmap = BitmapFactory.decodeFile(srcPath, opts);
//将图片旋转90°,旋转度数为:0-360,根据实际情况进行旋转
Bitmap resizePicture = rotatePicture(bitmap, 270);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int quality = 100;
resizePicture.compress(Bitmap.CompressFormat.JPEG, quality, baos);
System.out.println(baos.toByteArray().length);
//如果还大于2M,则循环减少
while (baos.toByteArray().length > 45 * 1024) {
baos.reset();
resizePicture.compress(Bitmap.CompressFormat.JPEG, quality, baos);
quality -= 20;
System.out.println(baos.toByteArray().length);
Log.i("wechat", "压缩后图片的大小" + (resizePicture.getByteCount() / 1024 / 1024)
+ "M宽度为" + resizePicture.getWidth() + "高度为" + resizePicture.getHeight() +
" byte.lenght" + (baos.toByteArray().length) / 1024 + "KB " + "quality=" + quality);
} try {
final File file = new File(fileName);//创建文件
if (!file.getParentFile().exists()) {
file.getParentFile().mkdir();//创建文件夹
}
//将bitmap写入流中
baos.writeTo(new FileOutputStream(fileName));
final String fa = file.getAbsolutePath();
Log.d("**图片存在的路径**", fa);
//上传base64位编码时,加上.replace("+", "%2B"),否则回出现上传失败
String encodeString = fileBase64String(fa).replace("+", "%2B");
Toast.makeText(getApplicationContext(), "拍照成功,照片保存在" + fa + "文件之中!", Toast.LENGTH_LONG).show();
Log.d("**base64**", encodeString);
final String destination = "body=" + encodeString + "";
new Thread(new Runnable() {
@Override
public void run() {
String post = HttpPost.SendPost(url_link, destination);
//上传成功后删除该照片
deleteSingleFile(fa);
Log.d("**数据已发送**", post.toString());
}
}).start();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
baos.flush();
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/** 删除单个文件
* @param filePath$Name 要删除的文件的文件名
* @return 单个文件删除成功返回true,否则返回false
*/
private boolean deleteSingleFile(String filePath$Name) {
File file = new File(filePath$Name);
// 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
if (file.exists() && file.isFile()) {
if (file.delete()) {
Log.e("--Method--", "删除单个文件" + filePath$Name + "成功!");
return true;
} else {
Log.e("--Method--", "删除单个文件" + filePath$Name + "失败!");
return false;
}
} else {
Log.e("--Method--", "删除单个文件" + filePath$Name + "不存在!");
return false;
}
}
/**
* 旋转90
* @param bitmap
* @param degree 旋转的度数
* @return
*/
public Bitmap rotatePicture(final Bitmap bitmap, final int degree) {
Matrix matrix = new Matrix();
matrix.postRotate(degree);
Bitmap resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
return resizeBitmap;
}
/**
*图片转bse64
* @param path 图片的路径
* @return
*/
private String fileBase64String(String path) {
try {
FileInputStream fis = new FileInputStream(path);//转换成输入流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int count = 0;
while ((count = fis.read(buffer)) >= 0) {
baos.write(buffer, 0, count);//读取输入流并写入输出字节流中
}
fis.close();//关闭文件输入流
String uploadBuffer = new String(Base64.encodeToString(baos.toByteArray(), Base64.NO_WRAP)); //进行Base64编码
return uploadBuffer;
} catch (Exception e) {
return null;
} }
//字体加粗
private void textsizi() {
TextView tv =findViewById(R.id.Btext);
TextPaint tp = tv.getPaint();
tp.setFakeBoldText(true);
}
//全透状态栏
protected void setStatusBarFullTransparent() {
if (Build.VERSION.SDK_INT >= 21) {//21表示5.0
Window window = getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
} else if (Build.VERSION.SDK_INT >= 19) {//19表示4.4
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//虚拟键盘也透明
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
}
@Override // 时间到就会执行此方法
public void onTimeOut(Screensaver screensaver) {
//关闭相机
mCameraView.stop();
linea_yingcangrenlian.setVisibility(View.GONE);
linea_menpai.setVisibility(View.VISIBLE);
//按钮标签初始化
imgbtn.setVisibility(View.VISIBLE);
//隐藏
darao.setVisibility(View.GONE);
dasao.setVisibility(View.GONE);
weixin.setVisibility(View.GONE);
text_menpai.setVisibility(View.GONE);
text_damenpai.setVisibility(View.VISIBLE);
} /**
* 单击事件
* @param view
*/
@SuppressLint("WrongConstant")
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.darao:
line_img_menling.setVisibility(View.GONE);
line_text_menling.setVisibility(View.GONE);
line_text_qingwudarao.setVisibility(View.VISIBLE);
int colr = darao.getTextAlignment();
if (1==colr){
darao.setBackground(getResources().getDrawable(R.drawable.btn_doorbell_dontdisturb_sel));
darao.setTextAlignment(2);
}
if (2==colr){
line_img_menling.setVisibility(View.VISIBLE);
line_text_menling.setVisibility(View.VISIBLE);
line_text_qingwudarao.setVisibility(View.GONE);
darao.setBackground(getResources().getDrawable(R.drawable.btn_doorbell_dontdisturb_unsel));
darao.setTextAlignment(1);
}
break;
case R.id.imgbut:
//菜单隐藏
imgbtn.setVisibility(View.GONE);
//请勿打扰显示-立即打扫显示-微信开门显示
darao.setVisibility(View.VISIBLE);
dasao.setVisibility(View.VISIBLE);
weixin.setVisibility(View.VISIBLE);
break;
case R.id.dasao:
Intent integer=new Intent(Ruzhu_Index_Activity.this, Dasao_Index_Activity.class);
startActivity(integer);
break;
case R.id.text_damenpai:
System.out.println(1111111);
Intent integer2=new Intent(Ruzhu_Index_Activity.this,Ganjing_Index_Activity.class);
startActivity(integer2);
break;
default:
break;
}
} @Override
protected void onDestroy() {
super.onDestroy();
if (mBackgroundHandler != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
mBackgroundHandler.getLooper().quitSafely();
} else {
mBackgroundHandler.getLooper().quit();
}
mBackgroundHandler = null;
}
} //定时调用
class task extends TimerTask {
@Override
public void run() {
Message msg = new Message();
msg.what = COMPLETED;
handler.sendMessage(msg);
}
}
//当触摸就会执行此方法
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
mScreensaver.resetTime(); //重置时间
return super.dispatchTouchEvent(ev);
}
} 最后别忘了在配置文件加上所需的权限
<uses-permission android:name ="android.permission .MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
 

Android使用com.google.android.cameraview.CameraView进行拍照的更多相关文章

  1. java.lang.VerifyError: com/google/android/gms/measurement/internal/zzw

    android studio  com.google.android.gms:play-services 运行报错:java.lang.VerifyError: com/google/android/ ...

  2. [Xamarin.Android] 如何使用Google Map V2 (转帖)

    Google Map v1已經在2013年的3月開始停止支援了,目前若要在你的Android手機上使用到Google Map,就必須要使用 到Google Map v2的版本.在Xamarin要使用G ...

  3. Android开发之Google Map

    2013-07-03 Google Map 提供三种视图: 1. 传统的矢量地图,提供行政区域.交通以及商业信息等. 2. 不同分辨率的卫星照片,与Google Earth 基本一样. 3. 地形地图 ...

  4. Google Android 6.0 权限完全解析

    注:本文只针对Google原生Android系统有效, 小米魅族等手机有自己的权限机制, 可能不适用 一.运行时权限的变化及特点 新的权限机制更好的保护了用户的隐私,Google将权限分为两类,一类是 ...

  5. linux kernel API and google android compile guide

    (1)linux kernel API website: http://docs.knobbits.org/local/linux-doc/html/regulator/index.html http ...

  6. [转]Android UI:看看Google官方自定义带旋转动画的ImageView-----RotateImageView怎么写(附 图片淡入淡出效果)

    http://blog.csdn.net/yanzi1225627/article/details/22439119 众所周知,想要让ImageView旋转的话,可以用setRotation()让其围 ...

  7. Introduction to Glide, Image Loader Library for Android, recommended by Google

    In the passed Google Developer Summit Thailand, Google introduced us an Image Loader Library for And ...

  8. 关于Google Android平台的ClockworkMod Recovery恢复模式

    lockworkMod Recovery,它也被称为Clockwork与CWM,它是装载Google Android操作系统设备的一个自定义的Recovery恢复模式,它可以使得相关Android设备 ...

  9. Re-install Flyme or Native Google Android on Meizu MX4 Ubuntu (by quqi99)

    作者:张华 发表于:2017-06-23 版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 ( http://blog.csdn.net/quqi99 ) ## ...

随机推荐

  1. linux命令积累

    lsof -i: //根据端口号查相关信息 //杀进程 ps -ef|grep appName //根据进程名称查找相关信息 grep -r "关键词" 目录 //在制定目录下根据 ...

  2. HashMap源码分析(一):JDK源码分析系列

    正文开始 注:JDK版本为1.8 HashMap1.8和1.8之前的源码差别很大 目录 简介 数据结构 类结构 属性 构造方法 增加 删除 修改 总结 1.HashMap简介 HashMap基于哈希表 ...

  3. web前端css(二)

    一.  标准文档流 标准文档流中会有一些现象: 空白折叠 和 高低不齐边底对齐的现象 标准文档流等级森严, 标签分为两种等级: 行内元素 和 块级元素. 1. 行内元素 和 块级元素的区别: 行内元素 ...

  4. Xilinx ISE如何调用Modelsim进行联合仿真

    图: 在对设计的芯片进行测试时,经常要用到FPGA,可是里面的仿真工具却不如Modelsim那么好用,且在规模比较大时,ISE在仿真时,软件经常会报告内存限制的问题,此时一般会切换到Modelsim软 ...

  5. flink window实例分析

    window是处理数据的核心.按需选择你需要的窗口类型后,它会将传入的原始数据流切分成多个buckets,所有计算都在window中进行. flink本身提供的实例程序TopSpeedWindowin ...

  6. 2019-2020年值得关注的9个AR发展趋势

    作者Andrew Makarov,由计算机视觉life编辑:乔媛媛编译 更好的阅读体验请看首发原文链接 2019-2020年值得关注的9个AR发展趋势 增强现实技术在2019年实现了创纪录的发展.微软 ...

  7. 【基础算法-模拟-例题-*校长的问题】-C++

    为什么在题目前面打上星号呢? 这道题的正解不是模拟! 正解树状数组! 正解树状数组! 正解树状数组! 重要的事情说够三遍了! 但是,歪解模拟因为数据水都能AC! 因为这道题放在模拟专题中,所以我们就讨 ...

  8. Excel催化剂开源第45波-按原图大小导出图片

    从Excel中导出图片,是一个很常规的需求,也有一些久旧不衰的界面操作法小技巧从OpenXml文件中批量导出,在VBA开发中,也会使用Chart对象的背景图的技巧来导出.总体来说,和真正想要的效果还是 ...

  9. [vue折线图] 记录SpringBoot+Vue3.0折线图订单信息展示

    因公司业务需求,需要做一份订单相关的折线图, 如果其中有一天没有订单的话,这一天就是空缺的,在绘制折线图的时候是不允许的,所有要求把没有订单数据的日期也要在图表显示. 使用技术vue3.0+sprin ...

  10. 安卓BindService笔记

    1 前言 最近学习到了安卓的service,记录一下自己对BindService的理解,学习教程以及部分代码来自菜鸟教程的android教程:菜鸟教程安卓端BindService链接 2 正文 先贴一 ...