最近一直在忙学校的新生杯扫地机器人irobot项目app,现在对开发过程中的一些问题进行总结。
一、因为App中需要用到较多按钮,固然可以一个一个地设置setOnClickListener,但也可以进行优化,代码如下
Button btn1,btn2;
btn1 = (Button)findViewById(R.id.btn1);
btn2 = (Button)findViewById(R.id.btn2);
View.OnclickListener listener = new OnclickListener(){
@Override
public void onClick( View view){
switch(view.getId()){
case R.id.btn1:
Log.d("btn1"," has been clicked! ");
break;
case R.id.btn2:
Log.d("btn2","has been clicked !");
break;
default:
break;
}
}
}
btn1.setOnclickListener(listener);
btn2.setOnclickListener(listener);
二、做的时候我在考虑怎么优化按钮的外观,发现用alpha可以改变按钮的透明度,代码如下:
android:alpha="1.0"
如何做出别的形状的按钮:
① 可以在Drawable 文件下下创建一个shape 的XML,示例代码如下:
corners用来设置圆角按钮
gradient设置渐变颜色,有liner,radial等选项,endColor和startColor为渐变的起始和终止渐变颜色
padding为设置文字与四边的间距
stroke为设置边框属性
完成该XML的创建后可以在要创建的Button中用background来设置:
android:background="@drawable/button_test"
② 也可以用ImageButton来设置,直接用src来设置想要作为背景的图片
(PS:这边我还遇到了一个小问题,即drawable下放入的图片只能用小写字母,且不能以数字开头)
三、关于如何设置标题栏
我发现app的标题栏在我的app中显得out of place, 于是实现标题栏的隐藏
① 在AndroidManifest中的
android:theme="@android:style/Theme.Holo.NoActionBar"
②在Java Class 中调用actionbar的hide方法
(第一行代码上的方法就是这个,进一步可以用back键绑定((Activity) getContext().finish();)来实现返回效果 )
如果想实现自定义的标题栏,新建XML(绑定事件的话再新建java class) 然后在布局中inflate
四、引入自定义字体的方法:
1、在网上下载字体文件(.ttf),并在工程目录的./main下,新建assets/fonts文件夹,并把.ttf文件放入其
中,如图
当然,如果不想在网上下载的话,就在C:\Windows\fonts下寻找对应的.ttf文件
2、在想要应用自定义字体的Activity Class中引入对应字体,代码如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textView;
textView = (TextView) findViewById(R.id.textview1);
Typeface typeface = Typeface.createFromAsset(getAssets(),"fonts/LHANDW.TTF");
textView.setTypeface(typeface);
if (savedInstanceState == null) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
BluetoothChatFragment fragment = new BluetoothChatFragment();
transaction.replace(R.id.sample_content_fragment, fragment);
transaction.commit();
}
}
这里只在TextView 中加载了对应字体
五、调整ProgressBar的外观:
final ProgressDialog progressDialog = new ProgressDialog(Welcome.this);
progressDialog.setMessage("Loading...");
progressDialog.setCancelable(false);
progressDialog.show();
Point size = new Point();
progressDialog.getWindow().getWindowManager().getDefaultDisplay().getSize(size); //一定要用progressDialog去得到
int width = size.x;
int height = size.y;
WindowManager.LayoutParams params = progressDialog.getWindow().getAttributes();
params.alpha = 1.0f; //设置进度条透明度
params.height = height/8; //设置进度条高度
params.gravity = Gravity.CENTER;
params.width = 4*width/5;
params.dimAmount = 0f; //设置半透明背景的灰度
六、关于用iRobot播放音乐
关键问题是得到音乐文件的二进制编码,由于下载的MP3或者MP4文件就是二进制的,这里直接用UltraEdit
打开就行。当然,考虑到MP4文件过大,而这里我们不需要那么好的播放效果,可以用.midi格式替代,大小只有
十几或者几十KB,却能包含数十条音
轨,这里截了一个关于百度百科对midi格式的说明,如下图:
七、蓝牙的连接
这个项目的核心问题就是要实现手机端与irobot上蓝牙模块的连接,这里我是下载的Github上的源码。结果发现连接不上。
一开始我以为是PIN码问题,后来发现不是,PIN码是用来实现配对的,这个配对可以在Android 手机中的Settings内完成,默认
的PIN码是1234或0000。而我是连接失败,这个连接问题一般是UUID问题。
UUID是设备的唯一识别码,由三部分组成,当前的日期和时间、时钟序列、全球唯一的IEEE设备识别号,如果有网卡,从
网卡MAC地址获得。UUID一般会比较长,对此使用比较广泛的是微软的GUID,在JAVA中可以用以下代码生成
import java.util.UUID;
public class Test {
public static void main(String[] args) {
UUID uuid = UUID.randomUUID();
System.out.println (uuid);
}
}
扯远了,我后来把源代码中的UUID修改了一下,发现竟然连接上了!具体原理大概是蓝牙串口通信或是不同的通信服务
需要特定的UUID吧,这里附上一个链接参考:https://blog.csdn.net/spmno/article/details/6931941
private static final UUID MY_UUID_SECURE =
//UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private static final UUID MY_UUID_INSECURE =
//UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
八、生成正式的.apk
注意如果res目录下的文件不是.png格式的就会出错,如果都是.png还是无法生成的话,可以试试删除图片重新下载或者
invalidate cache
九、Rockerview的引入
为了增强操作性,我通过引入第三方库另增了一个虚拟摇杆界面,可以在手指触摸的时候显示机器人前进的方向和速度值。
如图所示
十、横屏显示
因为这里我用了虚拟摇杆和几个按键组成的界面,横屏显示会更美观。步骤如下:
在res目录下新建resource file ,导入orientation, 并选择Landscape(landscape为横屏,portrait为纵向显示)
然后修改对应的Activity中的setcontentview即可,如图
十一、引入重力传感器
也是为了让我这个巨丑的界面显得更加酷炫,我加了个重力传感器,代码如下:
sensorManager =(SensorManager) getSystemService(Context.SENSOR_SERVICE);
Sensor accelerometersensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
Sensor magneticsensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
sensorManager.registerListener(listener,accelerometersensor,SensorManager.SENSOR_DELAY_GAME);
sensorManager.registerListener(listener,magneticsensor,SensorManager.SENSOR_DELAY_GAME);
@Override
protected void onDestroy() {
super.onDestroy();
if(sensorManager!=null){
sensorManager.unregisterListener(listener);
}
}
private SensorEventListener listener = new SensorEventListener() {
float[] accelerometerValues = new float[3];
float[] magneticValues = new float[3];
@Override
public void onSensorChanged(SensorEvent event) {
// 判断当前是加速度传感器还是地磁传感器
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
// 注意赋值时要调用clone()方法
accelerometerValues = event.values.clone();
} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
// 注意赋值时要调用clone()方法
magneticValues = event.values.clone(); }
float[] R = new float[9];
float[] values = new float[3];
SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticValues);
SensorManager.getOrientation(R, values);
Log.d("MainActivity", "value[0] is " + Math.toDegrees(values[0]));
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
这里采用的是加速度传感器和磁力传感器,代码我也是看的郭神的《第一行代码》上的。然后在Androidmanifest文件中加入以下支持:
表示加入传感器的权限,接着再在安卓手机的设置界面里找到权限,给对应app开启身体传感器权限。这里要注意如果不先在Androidmanifest 中加入对应支持,是无法在app中找到对应权限的。
项目代码:https://github.com/550517968/iRobot