找回密码
 马上注册

QQ登录

只需一步,快速开始

楼主: grant7788

记手机上Android系统编程的过程(手机可以读到NXT电量了)

   火.. [复制链接]
 楼主| 发表于 2011-3-3 17:03:48 | 显示全部楼层
本帖最后由 grant7788 于 2011-3-3 17:16 编辑

上面那个例子因为画了图,比较复杂。
我改一个简单的版本出来。以下是java程序:
  1. package com.TstSensor;

  2. import android.app.Activity;
  3. import android.hardware.Sensor;
  4. import android.hardware.SensorEvent;
  5. import android.hardware.SensorEventListener;
  6. import android.hardware.SensorManager;
  7. import android.os.Bundle;
  8. import android.widget.TextView;

  9. public class TstSensor extends Activity {
  10.     /** Called when the activity is first created. */
  11.         private SensorEventListener acc_listener = new SensorEventListener()
  12.         {
  13.                 @Override
  14.                 public void onAccuracyChanged(Sensor sensor, int accuracy)
  15.                 {
  16.                 }

  17.                 @Override
  18.                 public void onSensorChanged(SensorEvent event)
  19.                 {
  20.                         // Log.i("------", "" + "TYPE_ACCELEROMETER");
  21.                         tv1.setText("ACCELEROMETER_X: " + event.values[0]);
  22.                         tv2.setText("ACCELEROMETER_Y: " + event.values[1]);
  23.                         tv3.setText("ACCELEROMETER_Z: " + event.values[2]);
  24.                 }
  25.         };
  26.    
  27.         TextView tv1, tv2, tv3;
  28.     SensorManager mSensorManager;
  29.    
  30.     @Override
  31.     public void onCreate(Bundle savedInstanceState)
  32.     {
  33.         super.onCreate(savedInstanceState);
  34.         setContentView(R.layout.main);

  35.         tv1 = (TextView)findViewById(R.id.textView1);
  36.         tv2 = (TextView)findViewById(R.id.textView2);
  37.         tv3 = (TextView)findViewById(R.id.textView3);

  38.         mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
  39.     }

  40.     @Override
  41.     protected void onResume()
  42.     {
  43.         super.onResume();
  44.         mSensorManager.registerListener(acc_listener,
  45.                 mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
  46.                 SensorManager.SENSOR_DELAY_FASTEST);
  47.     }
  48.    
  49.     @Override
  50.     protected void onStop()
  51.     {
  52.         mSensorManager.unregisterListener(acc_listener);
  53.         super.onStop();
  54.     }
  55. }
复制代码



如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-3-3 17:04:25 | 显示全部楼层
下面是mail.xml的代码,其实很简单,就是加了三个TextView。
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:orientation="vertical"
  4.     android:layout_width="fill_parent"
  5.     android:layout_height="fill_parent"
  6.     >
  7. <TextView  
  8.     android:layout_width="fill_parent"
  9.     android:layout_height="wrap_content"
  10.     android:text="@string/hello"
  11.     />
  12. <TextView
  13.     android:text="TextView"
  14.     android:id="@+id/textView1"
  15.     android:layout_width="fill_parent"
  16.     android:layout_height="wrap_content">
  17. </TextView>
  18. <TextView
  19.     android:text="TextView"
  20.     android:id="@+id/textView2"
  21.     android:layout_width="fill_parent"
  22.     android:layout_height="wrap_content">
  23. </TextView>
  24. <TextView
  25.     android:text="TextView"
  26.     android:id="@+id/textView3"
  27.     android:layout_width="fill_parent"
  28.     android:layout_height="wrap_content">
  29. </TextView>
  30.    
  31. </LinearLayout>
复制代码
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-3-3 17:05:22 | 显示全部楼层
本帖最后由 grant7788 于 2011-3-3 17:41 编辑

除了代码中示范的显示加速度传感器的值,还有很多可以选。更新率也有数档可以选择。
大家可以看一下函数手册,换成其它你感兴趣的值。

Constants
int
A constant describing an accelerometer sensor type.
int
A constant describing all sensor types.
int
A constant describing a gravity sensor type.
int
A constant describing a gyroscope sensor type
int
A constant describing an light sensor type.
int
A constant describing a linear acceleration sensor type.
int
A constant describing a magnetic field sensor type.
int
This constant is deprecated. use
SensorManager.getOrientation()
instead.
int
A constant describing a pressure sensor type
int
A constant describing an proximity sensor type.
int
A constant describing a rotation vector sensor type.
int
A constant describing a temperature sensor type

// 以下的注释是我加的简单中文翻译
Constants // 常量

public static final int TYPE_ACCELEROMETER // 加速度传感器
Since: API Level 3
A constant describing an accelerometer sensor type. See SensorEvent.values for more details.
Constant Value: 1 (0x00000001)

public static final int TYPE_ALL // 所有传感器
Since: API Level 3
A constant describing all sensor types.
Constant Value: -1 (0xffffffff)


public static final int TYPE_GRAVITY // 重力传感器
Since: API Level 9
A constant describing a gravity sensor type. See SensorEvent for more details.
Constant Value: 9 (0x00000009)


public static final int TYPE_GYROSCOPE // 陀螺仪传感器
Since: API Level 3
A constant describing a gyroscope sensor type
Constant Value: 4 (0x00000004)


public static final int TYPE_LIGHT // 光强传感器
Since: API Level 3
A constant describing an light sensor type. See SensorEvent.values for more details.
Constant Value: 5 (0x00000005)


public static final int TYPE_LINEAR_ACCELERATION // 线性加速度传感器
Since: API Level 9
A constant describing a linear acceleration sensor type. See SensorEvent for more details.
Constant Value: 10 (0x0000000a)


public static final int TYPE_MAGNETIC_FIELD // 磁场传感器
Since: API Level 3
A constant describing a magnetic field sensor type. See SensorEvent.values for more details.
Constant Value: 2 (0x00000002)


public static final int TYPE_ORIENTATION  // 方向传感器
Since: API Level 3
This constant is deprecated.
use SensorManager.getOrientation() instead.
A constant describing an orientation sensor type. See SensorEvent.values for more details.
Constant Value: 3 (0x00000003)


public static final int TYPE_PRESSURE // 压力传感器
Since: API Level 3
A constant describing a pressure sensor type
Constant Value: 6 (0x00000006)


public static final int TYPE_PROXIMITY // 接近传感器 (返回的应该是距离)
Since: API Level 3
A constant describing an proximity sensor type. See SensorEvent.values for more details.
Constant Value: 8 (0x00000008)


public static final int TYPE_ROTATION_VECTOR // 旋转向量传感器
Since: API Level 9
A constant describing a rotation vector sensor type. See SensorEvent for more details.
Constant Value: 11 (0x0000000b)


public static final int TYPE_TEMPERATURE // 温度传感器
Since: API Level 3
A constant describing a temperature sensor type
Constant Value: 7 (0x00000007)


如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-3-3 17:10:39 | 显示全部楼层
程序很简单:
1. 在main.xml中,加入3个Textview以便后续显示。
2. 修改java程序:
2.1 加入SensorEventListener的实现。这个基本上可以理解成一个类,这个类中包含了数个回调函数(Callback Function),当传感器相关的事件发生时会被调用。
2.2 这个类中必须实现的是onAccuracyChanged,但是可以留成空的。
2.3 当传感器数值发生改变时,调用onSensorChanged事件,这里我们把传感器的值(Sensor.Values[]数组)显示出来。
3. 在OnCreate中,初始化三个TextView变量并赋值。并用mSensorManager变量取得传感器的使用权。
4. 在OnResume中,把回调函数的类(SensorEventListener)传给mSensorManager。
5. 在OnStop中,把回调函数停止。
以上用词可能不够专业或不够准确,大家有问题可以讨论。欢迎指正。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-3-3 17:49:52 | 显示全部楼层
本帖最后由 grant7788 于 2011-3-3 17:51 编辑

axis_device.png

传张图,这是加速感传感器传回的值的对应图。
Values[0] ==> X轴
Values[1] ==> Y轴
Values[2] ==> Z轴

加速器传感器返回的Sensor结构的成员变量:
Fields
public int
The accuracy of this event.
public Sensor
The sensor that generated this event.
public long
The time in nanosecond at which the event happened
public final float[]
The length and contents of the values array depends on which sensor type is being monitored (see also SensorEvent for a definition of the coordinate system used).


如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-3-3 23:17:55 | 显示全部楼层
今晚看了一阵子bluetooth的内容,觉得在Java / Android下的一些基础知识还需要补齐,比如Java下的多线程等。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-3-6 01:03:49 | 显示全部楼层

相当简化的Android手机上读取NXT电池电量的小程序

刚才做出来的小程序。把蓝牙连接的部分做了相当大的简化,基本上只保留了读写的部分。Java 主程序:

  1. package com.TstBluetooth;

  2. import java.io.InputStream;
  3. import java.io.OutputStream;
  4. import java.util.Iterator;
  5. import java.util.Set;

  6. import android.app.Activity;
  7. import android.bluetooth.BluetoothAdapter;
  8. import android.bluetooth.BluetoothDevice;
  9. import android.bluetooth.BluetoothSocket;
  10. import android.content.BroadcastReceiver;
  11. import android.content.Context;
  12. import android.content.Intent;
  13. import android.content.IntentFilter;
  14. import android.os.Bundle;
  15. import android.util.Log;
  16. import android.view.View;
  17. import android.widget.TextView;

  18. public class TstBluetooth extends Activity {
  19.         private BroadcastReceiver btMonitor = null;
  20.         private BluetoothAdapter btInterface;
  21.         private Set<BluetoothDevice> pairedDevices;
  22.    
  23.     final String tag = "TstBluetooth";
  24.     private BluetoothSocket socket;
  25.     private InputStream is = null;
  26.         private OutputStream os = null;

  27.         private boolean bConnected = false;
  28.     TextView tv1, tv2, tv3;
  29.             
  30.         /** Called when the activity is first created. */
  31.     @Override
  32.     public void onCreate(Bundle savedInstanceState) {
  33.         super.onCreate(savedInstanceState);
  34.         setContentView(R.layout.main);
  35.         
  36.         tv1 = (TextView)findViewById(R.id.textView1);
  37.         tv2 = (TextView)findViewById(R.id.textView2);
  38.         tv3 = (TextView)findViewById(R.id.textView3);
  39.         tv1.setText("Test Bluetooth...");
  40.         
  41.         // Setup btMonitor, to handle ACL_CONNECTED and ACL_DISCONNECTED event
  42.         setupBTMonitor();
  43.     }
  44.    
  45.     @Override
  46.         protected void onResume()
  47.     {
  48.                 super.onResume();
  49.                 Log.i(tag, "OnResume");
  50.                
  51.                 int iCount;
  52.                
  53.                 registerReceiver(btMonitor, new IntentFilter("android.bluetooth.device.action.ACL_CONNECTED"));
  54.                 registerReceiver(btMonitor, new IntentFilter("android.bluetooth.device.action.ACL_DISCONNECTED"));
  55.                 tv1.setText("onResume!");
  56.             findRobot(null);
  57.         }

  58.         @Override
  59.         protected void onPause() {
  60.                 super.onPause();
  61.                 Log.i(tag, "OnPause");
  62.             disconnectFromRobot(null);
  63.                 unregisterReceiver(btMonitor);
  64.         }

  65.         private void setupBTMonitor()
  66.     {
  67.             btMonitor = new BroadcastReceiver() {
  68.                     @Override
  69.                     public void onReceive(Context context, Intent intent){
  70.                             if (intent.getAction().equals("android.bluetooth.device.action.ACL_CONNECTED")) {
  71.                                     handleConnected();
  72.                             }
  73.                             if (intent.getAction().equals("android.bluetooth.device.action.ACL_DISCONNECTED")) {
  74.                                     handleDisConnected();
  75.                             }
  76.                     }
  77.             };
  78.     }
  79.    
  80.     private void handleConnected() {
  81.             try
  82.             {
  83.                 is = socket.getInputStream();
  84.                 os = socket.getOutputStream();
  85.                 bConnected = true;
  86.                 readNXTVoltage();
  87.             }
  88.             catch (Exception e)
  89.             {
  90.                     is = null;
  91.                     os = null;
  92.                     disconnectFromRobot(null);
  93.             }
  94.     }
  95.    
  96.     private void handleDisConnected()
  97.     {
  98.             bConnected = false;
  99.     }
  100.    
  101.     public void findRobot(View v)
  102.     {
  103.             try
  104.             {
  105.                     btInterface = BluetoothAdapter.getDefaultAdapter();
  106.                     Log.i(tag, "Local BT Interface name is [" + btInterface.getName() + "]");
  107.                     tv1.setText("Local BT Interface name is [" + btInterface.getName() + "]");
  108.                     pairedDevices = btInterface.getBondedDevices();
  109.                     Log.i(tag, "Found [" + pairedDevices.size() + "] devices.");
  110.                     tv1.setText("Found [" + pairedDevices.size() + "] devices.");
  111.                     Iterator<BluetoothDevice> it = pairedDevices.iterator();
  112.                     while (it.hasNext())
  113.                     {
  114.                             BluetoothDevice bd = it.next();
  115.                             Log.i(tag, "Name of peer is [" + bd.getName() + "]");
  116.                             if (bd.getName().equalsIgnoreCase("QIQI"))
  117.                             {
  118.                                     Log.i(tag, "Found Robot!");
  119.                                     Log.i(tag, bd.getAddress());
  120.                                     Log.i(tag, bd.getBluetoothClass().toString());
  121.                                     tv1.setText("Found Robot!");
  122.                                     tv2.setText(bd.getAddress());
  123.                                     tv3.setText(bd.getBluetoothClass().toString());
  124.                                     connectToRobot(bd);
  125.                                     return;
  126.                             }
  127.                     }
  128.             }
  129.             catch (Exception e)
  130.             {
  131.                     Log.e(tag, "Failed in findRotob()" + e.getMessage());
  132.             }
  133.     }
  134.    
  135.     private void connectToRobot(BluetoothDevice bd)
  136.     {
  137.             try
  138.             {
  139.                     socket = bd.createRfcommSocketToServiceRecord(java.util.UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
  140.                     socket.connect();
  141.             }
  142.             catch (Exception e)
  143.             {
  144.                     Log.e(tag, "Error interfacting with remote device [" + e.getMessage());
  145.             }
  146.     }
  147.    
  148.     public void disconnectFromRobot(View v)
  149.     {
  150.             try
  151.             {
  152.                     Log.i(tag, "Attemting to break BT connetion");
  153.                     socket.close();
  154.             }
  155.             catch (Exception e)
  156.             {
  157.                     Log.e(tag, "Error in DoDisconnect [" + e.getMessage() + "]");
  158.             }
  159.     }
  160.    
  161.     private void readNXTVoltage()
  162.     {
  163.             try
  164.             {
  165.                     tv1.setText("readNXTVoltage...");
  166.                     byte[] buffer = new byte[14];
  167.                     buffer[0] = 0x2;
  168.                     buffer[1] = 0x0;
  169.                     buffer[2] = 0x0;
  170.                     buffer[3] = 0xB;
  171.                 os.write(buffer);
  172.                 os.flush();
  173.                     tv1.setText("write to NXT...");
  174.                 Thread.sleep(1000);
  175.                 byte[] sizebuffer = new byte[2];
  176.                 int bytesRead = is.read(sizebuffer, 0, 2);
  177.                 int bytesReady = sizebuffer[0];
  178.                     tv1.setText("bytesReady = " + bytesReady + "[ " + sizebuffer[0] + " " + sizebuffer[1] + " ]");
  179.                 byte [] retBuf = new byte[bytesReady];
  180.                 bytesRead = is.read(retBuf);
  181.                 int LowByte = (retBuf[3]>=0? retBuf[3] : 256 + retBuf[3]);
  182.                 int HighByte = (retBuf[4]>=0? retBuf[4] : 256 + retBuf[4]);
  183.                 tv2.setText("[ " + LowByte + " " + HighByte + "]");
  184.                 int sVolt = HighByte * 256 + LowByte;
  185.                 tv3.setText("Volt = " + sVolt + " mV");
  186.             }
  187.             catch (Exception e)
  188.             {
  189.                     Log.e(tag, "Error write buffer!");
  190.             }
  191.     }
  192. }
复制代码



如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-3-6 01:06:13 | 显示全部楼层
main.xml的源码,其实很简单,就只加了三个文本显示(TextView)
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:orientation="vertical"
  4.     android:layout_width="fill_parent"
  5.     android:layout_height="fill_parent"
  6.     >
  7.     <TextView android:layout_height="wrap_content" android:layout_width="match_parent" android:text="TextView" android:id="@+id/textView1"></TextView>
  8.     <TextView android:layout_height="wrap_content" android:id="@+id/textView2" android:text="TextView" android:layout_width="match_parent"></TextView>
  9.     <TextView android:layout_height="wrap_content" android:id="@+id/textView3" android:text="TextView" android:layout_width="match_parent"></TextView>
  10. </LinearLayout>
复制代码



如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-3-6 01:07:26 | 显示全部楼层
为了取得蓝牙的权限,在另一个程序中要加一行:AndroidManifest.xml的源码。注意要加入蓝牙权限那行。
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3.       package="com.TstBluetooth"
  4.       android:versionCode="1"
  5.       android:versionName="1.0">
  6.     <uses-sdk android:minSdkVersion="8" />
  7.     <uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
  8.     <application android:icon="@drawable/icon" android:label="@string/app_name">
  9.         <activity android:name=".TstBluetooth"
  10.                   android:label="@string/app_name">
  11.             <intent-filter>
  12.                 <action android:name="android.intent.action.MAIN" />
  13.                 <category android:name="android.intent.category.LAUNCHER" />
  14.             </intent-filter>
  15.         </activity>

  16.     </application>
  17. </manifest>
复制代码



如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-3-6 01:10:48 | 显示全部楼层
本帖最后由 grant7788 于 2011-3-6 01:15 编辑

程序运行截图,以及APK文件。Android手机的朋友,如果有兴趣的话可以下载了试一下。这个程序没有做很多的处理,所以如果你想试的话,要先把NXT的主机名改成QIQI。
TstBluetooth.rar (14.6 KB, 下载次数: 21)

snap20110306_005246.png


如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-3-6 01:29:23 | 显示全部楼层
虽然没什么人支持,不过还是把程序的大致思路说一下。
我想做的,是在能够完成功能的情况下,尽可能地简化。所以查了一些资料以后,绕过了多线程。不过事件的处理还是必须的,或是说callback function。

0. 在AndroidManifest.xml中,加入以下一行,以让程序取得蓝牙权限。
(我开始没做这一条,结果始终读不回数据;加了异常处理以后,发现是产生了异常,报没有权限。)
    <uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>

1. 在main.xml中,加三个TextView,以便显示各种数据。
2. 在OnCreate中,调用setupBTMonitor(),这个函数的目的是处理ACL_CONNECTED和ACL_DISCONNECTED这两个事件。在蓝牙相关的程序中,这两个事件是必须处理的。

3. 在OnResume中,调用registerReceiver()函数,把2中所述的两个事件与btMonitor挂上钩。然后调用findRobot,开始真正打开蓝牙进行操作。

4. 看一下findRobot中的操作:
4.1 BluetoothAdapter.getDefaultAdapter(); ==> 蓝牙操作的第一步,取得适配器。
4.2 btInterface.getBondedDevices(); ==> 取得与本机配对过的设备列表。
4.3 while循环中,对这个列表进行遍历,找到指定名字的设备。(此处是"QIQI",我家的NXT主机名)
4.4 找到后,调用connectToRobot(bd);函数,进行连接。

5. 我们看一下connectToRobot(bd);这个函数的内容,如果不看异常处理的话,只有两句话:
                    socket = bd.createRfcommSocketToServiceRecord(java.util.UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
                    socket.connect();

在socket.connect();调用以后,就会激活我们前面讲的那两个事件。
如果连接成功,激活ACL_CONNECTED;如果不成功,则激活ACL_DISCONNECTED。

6. 我们看一下ACL_CONNECTED相对应的处理:handleConnected()
同样,不看异常处理的话,只有两句话:提供输入、输出的端口。

7. 连接完成以后,调用了读电量的程序:readNXTVoltage();
这里和我用VC / Python写过的程序是一样的,应该不用多说了:
发一串字符串下去,然后读一串回来;读回的数据的最后两位是电量的值,毫伏。
这里发现Java有个比较麻烦的地方,没有无符号字节变量。想了半天用了个笨办法解决了。
如果大家有好的方法请告诉我。谢谢。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-3-6 01:31:24 | 显示全部楼层
好晚了... 先睡了。
搞到现在基本上心比较定了:传感器的值已经可以读回了;蓝牙也可以连接了。
后面的事情就是如何通过蓝牙去控制小车,以及把控制小车的值和传感器的值联系起来。
应该不是很难了,慢慢来吧。

如我之前一个帖子说的,我最近实在是比较忙,头绪很多。
如果进度比较慢的话,请多点耐心。谢谢。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2011-3-9 17:37:12 | 显示全部楼层
不是没有人支持,是深度高了点,插不上嘴,现在都是依葫芦画瓢的
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-3-10 13:57:28 | 显示全部楼层
糖伯虎 发表于 2011-3-9 17:37
不是没有人支持,是深度高了点,插不上嘴,现在都是依葫芦画瓢的

呵呵,不急,等我把软件全部调通了,如果时间充裕,我出一个以图片为主的教程。这周杂事比较多,拖进度了。争取周五或周六多做点儿。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2011-4-8 21:12:17 | 显示全部楼层
强烈地想照葫芦画瓢,但是还是雾水中
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|中文乐高 ( 桂ICP备13001575号-7 )

GMT+8, 2024-3-19 14:43 , Processed in 0.842701 second(s), 19 queries .

Powered by Discuz! X3.5

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表