目标:防盗,当手机被盗远离口袋时发出报警声音,其原理是使用手机内置的距离传感器,检测到距离变化时播放报警声音
知识点:了解服务(service)的使用方法,调用手机传感器,播放声音
利用service后台监控手机的距离传感器,若检测到距离变化则播放报警声音,我们需要在AndroidManifest.xml中申请手机振动权限,并声明我们的服务组件,Android的四大组件使用时都要在这个文件中声明,AndroidManifest.xml文件如下:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="my.project.phonesecurity">
- <uses-permission android:name="android.permission.VIBRATE"></uses-permission><span style="white-space:pre"> </span><!--振动权限-->
- <application
- android:allowBackup="true"
- android:icon="@mipmap/ic_launcher"
- android:label="@string/app_name"
- android:supportsRtl="true"
- android:theme="@style/AppTheme">
- <activity android:name=".MainActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <span style="white-space:pre"> </span><!--注册服务组件-->
- <service android:name="my.project.phonesecurity.AntiTheftService"/>
- </application>
- </manifest>
设置距离报警服务:
上面我们注册了服务组件,接下来就要通过服务实现我们需要的功能,首先新建AntiTheftService类(与上面注册名称一致)继承Service父类,新建的类中会有一个onBind()方法,这是Service中唯一的抽象方法,我们不使用绑定方式启动服务,暂时忽略掉这个方法,重写onCreate()、onStartcommand()和onDestory()这三个方法,onCreate方法在服务创建的时候调用,onStartCommand会在每次服务启动的时候调用,onDstory在服务销毁的时候调用,我们在onCreate方法中获得传感器和振动服务并设置监听,加载音频等,在onDestory方法中停止播放音频,并取消传感器监听器。
传感器的使用方法都比较类似,首先第一步要获取到SensorManager的实例,SensorManager是系统所有传感器的管理器,通过调用getDefaultSensor()方法来得到任意的传感器类型:
Sensor sensor = sensorManager.getDefaultSeneor(Sensor.TYPE_PROXIMITY);
使用Sensor.TYPE_PROXIMITY常量来指定传感器类型。
- package my.project.phonesecurity;
- import android.app.Service;
- import android.content.Intent;
- import android.hardware.Sensor;
- import android.hardware.SensorEvent;
- import android.hardware.SensorEventListener;
- import android.hardware.SensorManager;
- import android.media.AudioManager;
- import android.media.SoundPool;
- import android.os.IBinder;
- import android.os.Vibrator;
- import android.util.Log;
- /**
- * Created by lx on 2017/9/4.
- */
- public class AntiTheftService extends Service {
- private static final String TAG = "PhoneSecurity";
- private SensorManager mgr; //传感器管理
- private Sensor proximity; //距离传感器
- private Vibrator vibrator; //振动马达
- private double lastVal = -1;
- private SoundPool soundPool;
- private int soundID = 0; //报警音效id
- private int streamID = 0; //报警音效播放流id
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
- @Override
- public void onCreate() {
- super.onCreate();
- //初始化音频资源池,加载报警音频
- soundPool = new SoundPool(10, AudioManager.STREAM_SYSTEM,5);
- soundID = soundPool.load(this,R.raw.beep,1);
- mgr = (SensorManager) getSystemService(SENSOR_SERVICE);
- proximity = mgr.getDefaultSensor(Sensor.TYPE_PROXIMITY);
- vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
- mgr.registerListener(proximityListener,proximity,SensorManager.SENSOR_DELAY_UI);
- }
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- Log.i(TAG,"服务启动");
- return super.onStartCommand(intent, flags, startId);
- }
- @Override
- public void onDestroy() {
- soundPool.stop(streamID);
- soundPool.unload(soundID);
- mgr.unregisterListener(proximityListener);
- super.onDestroy();
- }
- private SensorEventListener proximityListener = new SensorEventListener() {
- @Override
- public void onSensorChanged(SensorEvent event) {
- double thisVal = event.values[0];
- Log.d(AntiTheftService.TAG,"onSensorChanged["+thisVal+":"+lastVal+"]");
- if(lastVal == -1){
- //首次检测的值保存到lastVal,以便后面比较判断是否远离
- lastVal = thisVal;
- //短振动提示
- vibrator.vibrate(100);
- }
- else {
- if(thisVal != lastVal){
- //两次检测的距离不同,说明有异常,长振动并报警
- vibrator.vibrate(1000);
- if(streamID == 0){
- streamID = soundPool.play(soundID,1,1,0,-1,1);
- }
- }
- }
- }
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- }
- };
- }
界面实现:
设置三个按钮,一个用于开始服务,一个用于停止服务,一个将程序隐藏到后台,界面部分比较简单,主界面Activity如下:
- package my.project.phonesecurity;
- import android.app.Activity;
- import android.content.Intent;
- import android.os.Bundle;
- import android.view.View;
- import android.widget.Button;
- import java.util.Timer;
- import java.util.TimerTask;
- public class MainActivity extends Activity {
- Button startButton,stopButton,hideButton;
- private Timer timer;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- startButton = (Button) findViewById(R.id.startButton);
- stopButton = (Button) findViewById(R.id.stopButton);
- hideButton = (Button) findViewById(R.id.hideButton);
- startButton.setOnClickListener(new ButtonListener());
- stopButton.setOnClickListener(new ButtonListener());
- hideButton.setOnClickListener(new ButtonListener());
- }
- class ButtonListener implements View.OnClickListener{
- @Override
- public void onClick(View v) {
- switch(v.getId()){
- case R.id.startButton:
- //手机放入口袋需要时间,设置延迟
- int delay = 5000;
- timer = new Timer();
- timer.schedule(new TimerTask() {
- @Override
- public void run() {
- Intent intent = new Intent(MainActivity.this,AntiTheftService.class);
- startService(intent);
- }
- },delay);
- startButton.setClickable(false);
- stopButton.setClickable(true);
- break;
- case R.id.stopButton:
- if(timer != null) {
- timer.cancel();
- timer.purge();
- }
- Intent intent = new Intent(MainActivity.this,AntiTheftService.class);
- stopService(intent);
- startButton.setClickable(true);
- stopButton.setClickable(false);
- break;
- case R.id.hideButton:
- //实现home按键的效果,隐藏当前Activity界面
- Intent intent2 = new Intent(Intent.ACTION_MAIN);
- intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent2.addCategory(Intent.CATEGORY_HOME);
- startActivity(intent2);
- }
- }
- }
- }