您的位置:首页 > 移动开发 > Android开发

[Android]我的第一个手机应用

2013-02-22 16:10 447 查看
序:由于多次在Windows系统下Java开发环境安装不顺利,编写手机应用的尝试一直拖延到最近。

这个寒假我终于在自己的计算机上安装了Ubuntu系统,对我的影响确实很大。

这里长话短说,直切正题。回顾一下从一开始到第一个手机应用的诞生:本文简要总结Ubuntu系统下实现Android应用开发流程,以及最初的环境搭建。

关键字:Ubuntu/Eclipse/JDK/Android SDK/开发环境搭建/Android App/DDMS/USB调试

我的系统环境:
计算机 Lenovo Thinkpad X121e(32位的机型)
操作系统 Ubuntu 12.04 LTS
内存 3.8GiB
CPU Intel Core i3 @ 1.4GHz x4

第一部分 开发环境搭建

由于开发环境是前一段时间装的,现在已经记不清楚了,况且网上参考资料也很多,所以这里简单概括下,并列出我收藏的一些参考文献。为了节省篇幅这里不引用或翻译任何外来文字,只提供了链接以便参考。

1.安装Eclipse

一般开发Android应用使用Eclipse集成开发环境来编程(也可以用.Net+Mono的组合,这个还没有认真玩过)。

可以在终端直接输入eclipse,然后系统会提示这个还没有安装,并告诉你用什么指令可以安装。照着提示很快就能装好。

或者百度一下eclipse官方网站,下载相应的安装包(版本很多找.deb后缀、for Ubuntu,我的eclipse启动时有JUNO的字样,详见本章参考文献[1][2])。

2.安装JDK

同样可以在官方网站下载到。

安装完后在终端输入 java -version 检查一下版本是否是所需要的。

如果不是,cd /usr/bin 用 update-alternatives 命令修改 java jar javap javah 四个文件的链接以及优先级,使之最终指JDK安装位置的对应文件。(需要用sudo命令提升权限,详见本章参考文献[3])

3.安装Android SDK

参照Android官方网站中的Installing the Eclipse Plugin就可以顺利安装ADT(Android Development Tools)

打开Eclipse之后点击工具栏上的 Android SDK Manager 选择需要的API来安装。我只安装了Android 2.2 和 Android 4.0.3,因为我的手机(Meizu MX 4核)系统是从 Android 4.0.3 定制的,Android 2.2 作为系统最低要求。在 Android 4.0.3 下 SystemImage 包中我只选了ARM EABI v7a(同样因为我的手机处理器就属于ARM 7架构)。所以,简单起见,我只安装了那些自己需要的包。

提醒:安装之前的协议记得按Accept All,我一开始就是只按了Accept,以为就是接受了,其实只接受了一个包的协议,导致其他包没有安装。

4.配置***D(Android Virtual Device)

这个步骤是在建立一个模拟器,由于模拟器启动慢的原因,我不太愿意使用。但是否应该跳过这个步骤,这篇文章中的第一个Note可以帮助你决定:Using Hardware Devices

打开Eclipse之后点击工具栏上的 Android Virtual Device Manager,然后点击 New... 。主要是根据屏幕大小、储存器容量、CPU架构方面进行配置来建立一个模拟器,帮助你一廉价的方式完成在不同配置的设备上调试。

5.为使用DDMS(Dalvik Debug Monitor Server)作准备

这个步骤也是为真机调试作准备。在Ubuntu下配置USB规则(/etc/udev/rules.d/70-android.rules)。这个文件一开始不存在, sudo gedit 70-android.rules 之后输入这样一行文字:SUBSYSTEM=="usb",
SYSFS{idVendor}=="18d1", MODE="0666"

关于USB 规则的这个文件名,网络上的文献记载各不相同,这个文件名可以工作。如有异议可以自己具体搜索一下,因为这也可能跟系统平台有关系。其中要修改的就是SYSFS{idVendor}=="18d1"这一项中引号里的数值(代表了具体的设备)。这个数值是通过 lsusb 命令查得的(详见本章参考文献[4][5])。这个步骤的官方说明参考Using
Hardware Devices / Setting up a Device for Development

然后重启调试器有关的服务就完成了(详见本章参考文献[4][5])。

在Eclipse中点击 Window > Open Perspective > Other... > DDMS,就可以进入DDMS视图。以后每次进入Eclipse后进入DDMS视图,Eclipse就会自动启动调试器的有关服务,而无需手动启动,这篇文章中第一段提到了这一点:Debugging
from Eclipse with ADT

参考文献:

·[1]ubuntu下配置jdk+eclipse+android sdk

·[2]Ubuntu 12.04安装Java开发环境(jdk1.7 + Eclipse)

·[3]update-alternatives命令

·[4]ubuntu10.04 下通过usb在真机调试android程序的设置

·[5]步骤五的命令记录

alex@alex-ThinkPad-X121e:~$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 003: ID 147e:1002 Upek 
Bus 001 Device 004: ID 0a5c:217f Broadcom Corp. Bluetooth Controller
Bus 002 Device 003: ID 5986:01a6 Acer, Inc Lenovo Integrated Webcam
Bus 002 Device 013: ID 18d1:4e21 Google Inc. Nexus S
alex@alex-ThinkPad-X121e:~$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 003: ID 147e:1002 Upek 
Bus 001 Device 004: ID 0a5c:217f Broadcom Corp. Bluetooth Controller
Bus 002 Device 003: ID 5986:01a6 Acer, Inc Lenovo Integrated Webcam
Bus 002 Device 014: ID 18d1:4e22 Google Inc. Nexus S (debug)
alex@alex-ThinkPad-X121e:~$ cd /etc/udev
alex@alex-ThinkPad-X121e:/etc/udev$ cd rules.d
alex@alex-ThinkPad-X121e:/etc/udev/rules.d$ ls
70-persistent-cd.rules  70-persistent-net.rules  README
alex@alex-ThinkPad-X121e:/etc/udev/rules.d$ sudo gedit 70-android.rules
[sudo] password for alex: 
alex@alex-ThinkPad-X121e:/etc/udev/rules.d$ ls
70-android.rules  70-persistent-cd.rules  70-persistent-net.rules  README
alex@alex-ThinkPad-X121e:/etc/udev/rules.d$ cat 70-android.rules 
SUBSYSTEM=="usb", SYSFS{idVendor}=="18d1", MODE="0666"
alex@alex-ThinkPad-X121e:/etc/udev/rules.d$ sudo chmod a+rx /etc/udev/rules.d/70-android.rules
alex@alex-ThinkPad-X121e:/etc/udev/rules.d$ sudo service udev restart
udev stop/waiting
udev start/running, process 6898
alex@alex-ThinkPad-X121e:/etc/udev/rules.d$ cd ~
alex@alex-ThinkPad-X121e:~$ ls
asdk  examples.desktop  jws  Ubuntu One  模板  图片  下载  桌面
code  ftpshared         tmp  公共的      视频  文档  音乐
alex@alex-ThinkPad-X121e:~$ cd asdk
alex@alex-ThinkPad-X121e:~/asdk$ ls
add-ons  platforms       samples  system-images  tools
extras   platform-tools  sources  temp
alex@alex-ThinkPad-X121e:~/asdk$ cd tools
alex@alex-ThinkPad-X121e:~/asdk/tools$ ls
adb_has_moved.txt  emulator64-arm   jobb               sqlite3
android            emulator64-mips  lib                support
ant                emulator64-x86   lint               systrace
apkbuilder         emulator-arm     mksdcard           templates
apps               emulator-mips    monitor            traceview
ddms               emulator-x86     monkeyrunner       uiautomatorviewer
dmtracedump        etc1tool         NOTICE.txt         zipalign
draw9patch         hierarchyviewer  proguard
emulator           hprof-conv       source.properties
alex@alex-ThinkPad-X121e:~/asdk/tools$ cat adb_has_moved.txt 
The adb tool has moved to platform-tools/

If you don't see this directory in your SDK,
launch the SDK and ***D Manager (execute the android tool)
and install "Android SDK Platform-tools"

Please also update your PATH environment variable to
include the platform-tools/ directory, so you can
execute adb from any location.

alex@alex-ThinkPad-X121e:~/asdk/tools$ cd ..
alex@alex-ThinkPad-X121e:~/asdk$ cd platform-tools/
alex@alex-ThinkPad-X121e:~/asdk/platform-tools$ ls
aapt  aidl  dexdump  fastboot  llvm-rs-cc  renderscript
adb   api   dx       lib       NOTICE.txt  source.properties
alex@alex-ThinkPad-X121e:~/asdk/platform-tools$ sudo ./adb kill-server
alex@alex-ThinkPad-X121e:~/asdk/platform-tools$ ./adb devices
List of devices attached 
MX21CA2ALGPES22334	device

alex@alex-ThinkPad-X121e:~/asdk/platform-tools$ ./adb root
adbd cannot run as root in production builds
alex@alex-ThinkPad-X121e:~/asdk/platform-tools$


第二部分 编写 Android 应用程序

这个部分的没有列举参考文献,因为参考文献比较好找,并且过程也比搭建环境简单。这里介绍一下我开发的第一个手机应用程序的开发过程,来示范一下开发的简要流程。由于个人对C/C++以及C#编程都很熟悉,所以Java上手很快,没有遇到周折。

1.真机运行 HelloWorld

这个步骤是为了避免一些低级错误的发生。先新建一个Project(Android Project / Android Application Project)。如果新建工程的表单中某些项有警告或错误标识(文字旁的一个小图标),说明还有一些项目需要安装(如API、System Image...),检查并完成安装(参考第一部分)。然后把手机设置成USB 调试模式,并通USB数据线连接计算机。在左侧(Java 视图)中右击工程那一项,点击 Run As
> Android Application。Eclipse就会在手机上自动部署应用程序并启动。看到了跟设计视图中一样的图形界面,中间写着 Hello World 的字样,就说明一切已经准备就绪可以开始编程了。如果不能下载进去而显示了一些adb的错误,那么先进入DDMS视图来启动调试服务(参考第一部分/步骤5/第4段)。

2.设计界面

Android的UI是通过xml的形式来表示的,就类似于网页一样。在工程中找 res > layout > *.xml 就是布局有关的文件,双击打开后,Eclipse会提供可视化设计视图以及xml代码。自己摆弄一下这些空间,看看xml对用有什么变化,如果之前有过WPF、网页或其他类似的开发经验的话很快就知道怎么设计界面了,为了节省篇幅这里就不列举了。Android应用界面中静态的文本可以放在 res > values > strings.xml
当中,可以通过可视化方式设计、更改。

截图:



界面代码:

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:layout_marginTop="16dp"
        android:text="@string/ruletext" />

    <TextView
        android:id="@+id/textViewTotal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView1"
        android:layout_below="@+id/textView1"
        android:layout_marginTop="16dp"
        android:text="@string/total"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <SeekBar
        android:id="@+id/seekBarTotal"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textViewTotal"
        android:layout_alignRight="@+id/textView1"
        android:layout_below="@+id/textViewTotal"
        android:max="60" />

    <TextView
        android:id="@+id/TextViewK"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/seekBarTotal"
        android:layout_below="@+id/seekBarTotal"
        android:layout_marginTop="20dp"
        android:text="@string/lottery"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <SeekBar
        android:id="@+id/SeekBarK"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/TextViewK"
        android:layout_alignRight="@+id/seekBarTotal"
        android:layout_below="@+id/TextViewK"
        android:max="61" />

    <TextView
        android:id="@+id/textViewKing"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignLeft="@+id/SeekBarK"
        android:layout_alignParentBottom="true"
        android:layout_alignTop="@+id/buttonDo"
        android:layout_marginRight="30dp"
        android:text="@string/king"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textSize="42sp" />
    
    <Button
        android:id="@+id/buttonDo"
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/textView1"
        android:layout_below="@+id/SeekBarK"
        android:layout_marginRight="25dp"
        android:layout_marginTop="0dp"
        android:onClick="onButtonGetKing"
        android:text="@string/getking" />

</RelativeLayout>


strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">MonkeyLottery</string>
    <string name="menu_settings">Settings</string>
    <string name="ruletext">猴王大选:所有猴子围坐一圈,1至K报数,凡报到K的猴子退出到圈外,如此循环,直到圈内只剩下一只猴子即猴王。</string>
    <string name="total">总数 =</string>
    <string name="lottery">K =</string>
    <string name="king">猴王</string>
    <string name="getking">计算猴王</string>

</resources>


3.订阅事件

在Android中经常采用事件侦听的方式来订阅事件。看这里的SeekBar的事件都是怎么订阅的:

MainActivity.java 片段

private SeekBar seekBarTotal,seekBarK;
	private TextView textViewTotal,textViewK,textViewKing;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		seekBarTotal = (SeekBar) this.findViewById(R.id.seekBarTotal);
		seekBarK = (SeekBar) this.findViewById(R.id.SeekBarK);
		textViewTotal = (TextView) this.findViewById(R.id.textViewTotal);
		textViewK = (TextView) this.findViewById(R.id.TextViewK);
		textViewKing = (TextView) this.findViewById(R.id.textViewKing);
		seekBarTotal.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
			@Override public void onStopTrackingTouch(SeekBar seekBar){}
			@Override public void onStartTrackingTouch(SeekBar seekBar){}
			@Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser){
				textViewTotal.setText("总数 = "+Integer.toString((int)Math.pow(1.161584, progress)+1));
			}});
		seekBarK.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
			@Override public void onStopTrackingTouch(SeekBar seekBar){}
			@Override public void onStartTrackingTouch(SeekBar seekBar){}
			@Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser){
				textViewK.setText("K = "+Integer.toString(progress+2));
			}});
		seekBarTotal.setProgress(23);//32
		seekBarK.setProgress(13-3);//13
		//default answer 28
	}


如果缺少引用就右击那个类,选择 Quick Fix > Import ...

按钮的点击事件很容易订阅:设置下onClick属性(参考activity_main.xml最后一块代码),然后在Java中实现同名函数就可以了。(下一步骤将完成这个例子)

4.实现算法

用Java实现一个算法,让程序运行起来。这里我选择了这样一个问题作为例子:

猴王大选:所有猴子围坐一圈,1至K报数,凡报到K的猴子退出到圈外,如此循环,直到圈内只剩下一只猴子即猴王。

这是C语言习题中会列举的,典型的链表应用实例。这里的lms数组隐式地实现了利用链表的算法,为了不偏离主题,这里就忽略对这个问题的分析了,下面贴出求解的源代码,来完成整个开发流程。

MainActivity.java 片段

private short[] lms=new short[8000];
	public void onButtonGetKing(View view){
		int n=(int)Math.pow(1.161584, seekBarTotal.getProgress())+1,a=seekBarK.getProgress()+2,m=0;
		for(int i=0;i<n-1;i++)lms[i]=(short)(i+1);
		lms[n-1]=0;
		for(int c=n;c>1;c--){
	        for(int j=1;j<a-1;j++)m=lms[m];
	        m=lms[m]=lms[lms[m]];
	    }
		textViewKing.setText(Integer.toString(m+1));
	}


MainActivity.java

package com.byalex.ahello;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.SeekBar;
import android.widget.TextView;

public class MainActivity extends Activity {
private SeekBar seekBarTotal,seekBarK; private TextView textViewTotal,textViewK,textViewKing; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); seekBarTotal = (SeekBar) this.findViewById(R.id.seekBarTotal); seekBarK = (SeekBar) this.findViewById(R.id.SeekBarK); textViewTotal = (TextView) this.findViewById(R.id.textViewTotal); textViewK = (TextView) this.findViewById(R.id.TextViewK); textViewKing = (TextView) this.findViewById(R.id.textViewKing); seekBarTotal.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar){} @Override public void onStartTrackingTouch(SeekBar seekBar){} @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser){ textViewTotal.setText("总数 = "+Integer.toString((int)Math.pow(1.161584, progress)+1)); }}); seekBarK.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar){} @Override public void onStartTrackingTouch(SeekBar seekBar){} @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser){ textViewK.setText("K = "+Integer.toString(progress+2)); }}); seekBarTotal.setProgress(23);//32 seekBarK.setProgress(13-3);//13 //default answer 28 }

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
private short[] lms=new short[8000]; public void onButtonGetKing(View view){ int n=(int)Math.pow(1.161584, seekBarTotal.getProgress())+1,a=seekBarK.getProgress()+2,m=0; for(int i=0;i<n-1;i++)lms[i]=(short)(i+1); lms[n-1]=0; for(int c=n;c>1;c--){ for(int j=1;j<a-1;j++)m=lms[m]; m=lms[m]=lms[lms[m]]; } textViewKing.setText(Integer.toString(m+1)); }
}


5.最后是一张截图:这就是我的第一个手机应用


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: