zoukankan      html  css  js  c++  java
  • android应用开发全程实录实现甩动拨打和挂断电话

    今天继续给大家带来《Android应用开发全程实录》中的章节,这部分是讲传感器中的一个实例。

    通过上面的例子我们学会了如何获得某种类型的传感器,下面通过一个实例来学习如何使用某一个类型的传感器。我们以加速传感器为例,来实现这样一个功能:摇动手机便自动拨打某亲情号码,并实现再次摇动则挂机的功能。

     

    工程目录:EX_12_03

    第一步,UI布局main.xml的代码如下,其运行效果如图12-10所示。

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation
    ="vertical"
    android:layout_width
    ="fill_parent"
    android:layout_height
    ="fill_parent" >
    <TextView android:layout_width="fill_parent"
    android:layout_height
    ="wrap_content"
    android:text
    ="当前状态:就绪"
    android:id
    ="@+id/state"
    android:textColor
    ="#ff0000" />
    <Button android:layout_width="fill_parent"
    android:layout_height
    ="wrap_content"
    android:id
    ="@+id/call"
    android:text
    ="打电话(10086)"/>
    <Button android:layout_width="fill_parent"
    android:layout_height
    ="wrap_content"
    android:id
    ="@+id/stop"
    android:text
    ="挂机"/>
    </LinearLayout>

    第二步,挂电话需要用到系统的Itelephony类的支持,由于Google从Android 2.1 SDK版本后,屏蔽了com.android.internal.telephony. Itelephony类,因此,需要从Android源码下载,找到该类并导入到工程目录下,记得包名一致。

    第三步,Activity类ShakeSensorActivity的实现。该类实现SensorListener接口,添加加速度侦听事件,通过判断设备X、Y、Z方向的总晃动值来判断是否启动打电话和挂机操作。以拨打10086测试为例,当设备总晃动值大于100作为一个测试判断点,如果当前没有在通话界面,就通过Intent启动拨打电话,否则就挂机操作。设备摇动时,启动电话、挂机的界面状态如图图12-11、图12-12所示。

     

     

    ▲图12-10  软件运行效果图            12-11  电话启动界面                                   12-12  摇动设备挂机时的状态界面

    下面就来看看代码:

    public class ShakeSensorActivity extends Activity implements SensorListener {
    private float lastX;
    private float lastY;
    private float lastZ;
    private View mainView;
    private long currTime;
    private long lastTime;
    private long duration;// 持续时间 
    private float currShake;
    private float totalShake;
    private ITelephony iTelephony;
    private boolean isCalling = false;
    SensorManager sm = null;
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mainView = LinearLayout.inflate(this, R.layout.main, null);
    setContentView(mainView);
    ((Button) mainView.findViewById(R.id.call)).setOnClickListener(new
    OnClickListener() {
    @Override
    public void onClick(View v) {
    // 打电话
    callPhoneNumber10086();
    }
    });
    ((Button) mainView.findViewById(R.id.stop)).setOnClickListener(new OnClick- Listener() {
    @Override
    public void onClick(View v) {
    // 挂机
    closePhone();
    }
    });
    // 获取传感器管理器
    sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    // 注册加速度传感器 
    sm.registerListener(this,
    SensorManager.SENSOR_ACCELEROMETER,SensorManager. SENSOR_DELAY_NORMAL);

    }
    @Override
    public void finish() {
    // TODO Auto-generated method stub
    super.finish();
    sm.unregisterListener(this);// 注销侦听

    }
    @Override
    public void onAccuracyChanged(int sensor, int accuracy) {
    // 精度改变,该方法实质上不做任何操作,它只在每次调用时,添加一个日志项
    }
    @Override
    public void onSensorChanged(int sensor, float[] values) {
    float x = values[0];
    float y = values[1];
    float z = values[2];
    currTime = System.currentTimeMillis();
    if (lastX == 0 && lastY == 0 && lastZ == 0) {
    // 第一次shake
    lastTime = currTime;
    }
    if (currTime - lastTime > 200) {// 200毫秒检测一次
    duration = currTime - lastTime;
    currShake = (Math.abs(x - lastX) + Math.abs(y - lastY) + Math.abs(z - lastZ))/ duration * 200;
    }
    totalShake = totalShake + currShake;
    if (totalShake > 100) {
    totalShake = 0;// 重置为0,重新累计计数
    lastX = 0;
    lastY = 0;
    lastZ = 0;
    lastTime = 0;
    currTime = 0;
    if (!isCalling) {
    callPhoneNumber10086();
    ((TextView) mainView.findViewById(R.id.state)).setText("当前状态: 通话中...");
    } else {
    closePhone();
    ((TextView) mainView.findViewById(R.id.state)).setText("当前状态:通话结束...");
    }
    }
    lastX = x;
    lastY = y;
    lastZ = z;
    lastTime = currTime;
    }

    /**
    * tell 10086打开通话界面
    */
    private synchronized void callPhoneNumber10086() {
    isCalling = true;
    Intent myIntentDial = new Intent(Intent.ACTION_CALL,Uri.parse("tel:" + 10086));
    startActivity(myIntentDial);
    }

    /**
    * 结束通话
    */
    private synchronized void closePhone() {
    try {
    getTelephony();
    iTelephony.endCall();
    isCalling = false;
    } catch (RemoteException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

    }

    /**
    * 初始电话 实例
    */
    public void getTelephony() {

    TelephonyManager telMgr = (TelephonyManager)
    this.getSystemService(Service. TELEPHONY_SERVICE);
    Class<TelephonyManager> c = TelephonyManager.class;
    Method getITelephonyMethod = null;
    try {
    getITelephonyMethod = c.getDeclaredMethod("getITelephony",(Class[]) null);
    getITelephonyMethod.setAccessible(true);
    } catch (SecurityException e) {
    e.printStackTrace();
    } catch (NoSuchMethodException e) {
    e.printStackTrace();
    }

    try {
    iTelephony = (ITelephony)
    getITelephonyMethod.invoke(telMgr,(Object[])null);
    } catch (IllegalArgumentException e) {
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    e.printStackTrace();
    } catch (InvocationTargetException e) {
    e.printStackTrace();
    }

    }

    通过getTelephony()方法,初始一个iTelephony实例,方便调用,目前只用到了挂机关闭通话,打电话也可以通过iTelephony.dial(“10086”)直接拨打。这样就轻松实现了用传感器实现甩动打、挂电话功能。



  • 相关阅读:
    == 和 equals 的区别是什么?
    String 类的常用方法都有那些?
    报表工具对比选型系列—多样性数据源支持度
    报表工具选型对比系列
    报表工具选型对比系列
    web 端怎么实现套打发票、快递单等套打票据功能?
    如何集成一个第三方报表,权限怎么控制
    BI 报表工具如何与 springBoot 框架集成
    在报表中可以使用 ECharts 做图形展现吗?
    Tableau 等常见 BI 工具能集成到 java 项目中吗
  • 原文地址:https://www.cnblogs.com/noTice520/p/2303492.html
Copyright © 2011-2022 走看看