心血来潮,走进Android,准备开发一个摇一摇分歧表决器(PS:这个想法源自去年看的一个都市剧《约会专家》中主人公杭杭开发的分歧表决器APP)。
简述:摇一摇分歧表决器是一款Android App,通过将传统的手头剪刀布分歧表决游戏移植到智能手机上,玩家可以通过摇动手机还获取结果,PK对家。 (汗!)
目标:一款简单,易用的Android分歧表决App
设备要求:加速传感器,Android系统
涉及知识点:Android ImageView,TextView,RelativeLayout,Sensor,Vibrator,SoundPool
开始动手:
1.在Eclipse中创建Android 项目
2.准备资源文件,石头,剪刀,布,和玩法示意图,AppIcon四张图片,结果提示音(mp3)
3.创建布局文件(activity_splitter.xml)
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ImageView android:id="@+id/p_w_picpath_result" android:layout_width="match_parent" android:layout_height="375dp" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:contentDescription="@string/p_w_picpath_desc_msg" android:scaleType="fitXY" android:scrollbars="none" android:src="@drawable/rules" /> <TextView android:id="@+id/text_msg" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/p_w_picpath_result" android:layout_centerVertical="true" android:layout_marginTop="50dp" android:gravity="center_horizontal" android:text="@string/user_method_msg" android:textStyle="bold" /> </RelativeLayout>
4.实现思路
4.1启动App,在ImageView中展示玩法图片,TextView显示玩法说明;
4.2玩家摇动手机,应用程序通过加速传感器获得手机加速度,当加速度达到指定范围,发送更新UI界面消息;
4.3通过消息处理机制,更新UI界面,在ImageView中展示结果图片(石头,剪刀,布三者之一),TextView显示对应的文字说明,并伴随提示音和轻微震动。
5.开发实现
5.1该应用极其简单,仅有一个Activity,在ApplicationManifest.xml中配置启动界面
<activity android:name=".SplitterActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
5.2应用程序使用到设备的震动,在ApplicationManifest.xml中配置权限
<uses-permission android:name="android.permission.VIBRATE" />
5.3具体开发Activity
需要熟悉:SensorManager,Sensor,SoundPool,Handler这几个类的使用,自己实现SensorEventListener接口方法,如下onSensorChanged,onAccuracyChanged方法。
public class SplitterActivity extends Activity implements SensorEventListener { private ImageView p_w_picpathViewResult; private TextView textViewMsg; private int[][] result = new int[][] { { R.drawable.rock, R.string.rock_result_msg }, { R.drawable.paper, R.string.paper_result_msg }, { R.drawable.scissors, R.string.scissors_result_msg } }; private SensorManager sensorManager; private Sensor sensor; private Vibrator vibrator; private SoundPool soundPool; private int streamSoundId; private static final int UPDATE_VIEW = 0x01; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == UPDATE_VIEW) { if (vibrator.hasVibrator()) { vibrator.vibrate(new long[] { 200L, 500L }, -1); } soundPool.play(streamSoundId, 0.5F, 0.5F, 5, 0, 1.0F); Random random = new Random(); int index = random.nextInt(result.length); p_w_picpathViewResult.setImageResource(result[index][0]); textViewMsg.setText(result[index][1]); } } }; public SplitterActivity() { } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.activity_splitter); p_w_picpathViewResult = (ImageView) this.findViewById(R.id.p_w_picpath_result); textViewMsg = (TextView) this.findViewById(R.id.text_msg); sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); vibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE); soundPool = new SoundPool(10, AudioManager.STREAM_SYSTEM, 5); streamSoundId = soundPool.load(this, R.raw.call_result, 0); } @Override protected void onResume() { super.onResume(); sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL); } @Override protected void onStop() { sensorManager.unregisterListener(this); if (null != vibrator) { vibrator.cancel(); vibrator = null; } if (null != soundPool) { soundPool.release(); soundPool = null; } super.onStop(); } @Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { float[] values = event.values; if (isNormalAcceler(values)) { new Thread(new Runnable() { @Override public void run() { Message msg = new Message(); msg.what = UPDATE_VIEW; handler.sendMessage(msg); } }).start(); } } } private boolean isNormalAcceler(float[] values) { int g = 15; return (Math.abs(values[0]) > g && Math.abs(values[1]) > g) || Math.abs(values[2]) > g; } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { BackListener backListener = new BackListener(); new AlertDialog.Builder(this) .setIcon(android.R.drawable.ic_dialog_info) .setTitle(R.string.app_name) .setMessage(R.string.exite_app_info) .setPositiveButton(R.string.leave, backListener) .setNegativeButton(R.string.without, backListener).show(); return true; } return super.onKeyDown(keyCode, event); } private class BackListener implements DialogInterface.OnClickListener { @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case DialogInterface.BUTTON_POSITIVE: SplitterActivity.this.finish(); break; case DialogInterface.BUTTON_NEGATIVE: break; default: break; } } } }
6.效果图
7.总结
通读了Android官方开发文档之后,感觉不得要领。唯找出一个目标App,进行模仿,在此过程不断深入了解其中原理,API文档,反复回顾Android开发知识体系,久而久之就能开发自己的想要的Android应用了。
另外就是针对某一知识点,比如:Activity,ContentProvider,View 等做示例,实验,探究;最后将四大组件,各种布局结合起来,集成各种服务实现完备应用,这样就基本掌握了Android开发。接下来就该深入探究其中机理。