n62 脚印

阅读全文

(原作时间:2011-02-13) 年后刚刚回来的那一天下雪了.我是盼着下雪的没错,但是它选择了一个尴尬的时间,于是导致我在飞机上多待了1个多小时等它起飞.. 当一个人倒霉了的时候,最直接的让他开心起来的办法就是,让他发现,有更倒霉的人. 这个人就是曾经想杀我灭口的室友maqi(参考文献:n61). maqi从上海到北京,原本说是两三点钟就到了,拎了行李就可以回家了.但是,当他在行李的传送带旁等了N久之后发现没找到自己的行李.这不行啊,于是他就去找了工作人员.工作人员说,这不可能,我们一起去找.然后找到一个很像的,问maqi,是不是这个?maqi说,不是.工作人员:你确定真的不是么?maqi:真的不是...工作人员:唔...大概被拿错了...我帮你再去查一下. 于是工作人员查了下(我也不知道查的是什么),发现,万幸的是,这箱子并不是被别人错拿了,而是..压根就还在上海卡在送上飞机的途中了...于是工作人员跟maqi说,要么你先回去..我们帮你把它放到六点多的飞机上,然后再给你把行李送过去. maqi想妥协,但他不能妥协.虽然箱子里几乎没有任何重要的东西,不过是一些零碎的譬如食物之类.但是注意这个"几乎",因为有一个小小的东西让maqi心碎,那就是,钥匙. 据当事人maqi回忆,上飞机前他也曾犹豫,到底这个钥匙放在什么地方合适.在不经意间,他犯下了让他追悔莫及的错误,那就是,没有把钥匙随身携带. 更加关键的是,maqi是我们寝室三个人中最先到北京的,也就是说,他走投无路... 于是他等到了九点多才到家,然后一病不起,第二天就没去上班... 我听maqi讲完了这个惊心动魄的故事,感觉很爽.于是发现,自己不是很倒霉. 这是发生在maqi身上的杯具. 没关系,我们继续看下一个杯具. 这是发生在linyi身上的. 在我给linyi讲完maqi的故事之后,他也很开心地嘲笑了maqi. 昨天,我和maqi说,我们去看话剧吧,上次的<乌龙山伯爵>还是不错的,这次我们去再看一部开心麻花的剧,<江湖学院>.我问linyi(当时我不知道他已经到了北京了,以为他是第二天回来),你能去么,你想去么,你会去么. linyi说,没激情,不去. 于是linyi也要为他的选择付出代价. 我这次学乖了,买了很靠后的位置.因为上一次430的套票,位置也并不是想象中那么好,还是看不到演员的表情.这次我直接冲着最后一排的座位去了.同时,去京东上买了个望远镜.. 其实这个决定还是很正确的.反正看不清脸,听听声音吧..想看的时候就用望远镜... 我和maqi下班之后就直接去坐地铁赶场子了.当我们到达了积水潭站准备去剧场的时候(大概7点左右),我们接到了linyi的电话,据其表示,他忘记带钥匙了. 我们告诉他,我们19:30开始看,起码要看2个半小时,然后坐地铁回去也是1小时,你就先在公司加加班,等23点左右再回家吧. 于是linyi年后上班第一天,就"加班"到了晚上十一点... 这次话剧没有上次的好看,没有特别突出的搞笑人物,就是张子栋的出现让我惊喜了一下. 不过,我们依然怀着欢乐的心情(主要是嘲笑linyi),看完了两个半小时.然后,悠闲地在附近的肯德基吃了一顿晚餐才回去... 今年到了本命年了.一直诚惶诚恐的.毕竟说是,本命年是不好过的,会有诸如"血光之灾"的东西.例如在公司吃完饭散步的时候差点儿摔在结了冰的池子里之类(当然了,我凭借顽强的意志力和惊人的平衡力得到了安稳落地的满分,但是,这样的成功不可复制,更加不可粘贴). 下的雪很干脆.从连云港到北京都是.深夜到了北京,坐大巴到了中关村等车,突然发现的确挺冷的,而且饿了. 又是和别人拼的车,我是最远的一个,坐车到了附近的肯德基(tmd,又是肯德基..),因为我印象中附近的24小时营业的店就数到它了..其时地上已经是有了相当厚度的积雪了. 走回小区,转头看了一下,只有一步一个脚印,孤零零的一排. 貌似今年真的是很关键的一年,需要好好想一想,类似于"归属地"之类的事情. 所谓的"成长"从来都不是像方波一样的突变,是要像胡子一样,艰难地从厚厚的脸皮中冒出头来并挣扎着出来才对. 说起来,过年在家,貌似又是没做什么事儿,做的最多的无非就是小小的聚会和喝酒.烧烤吃了3次,软陶做了5个,麻将打了1次(还tmd输了..),目睹南大山着火1次. 初一晚上,从舅舅家回来,发现山上很明亮,细看是着了火,还是很凶的. 小时候家附近是个庵堂,现在变成了一个寺.经过的时候,我总是在想,里面现在到底是尼姑,还是和尚. 又累了,不知该再写什么了.

The post n62 脚印 appeared first on 邮递员大叔.

阅读全文>>

n61 岁月

阅读全文

(原作时间:2011-01-02) maqi说,要消除我的记忆. 我必须趁着他还没有这么做之前,把这件事情记录下来. 如果说,什么时候我突然消失了,请记得,我是为了正义. 今天maqi如同打了鸡血一样非常hi,莫不是因为gj走掉了?又是买菜又是做饭又是洗碗又是拖地板... 重要的不是这个. 重要的是,maqi早上去买菜.其时,我还不算是完全地起床了.maqi就非常激动地说,去买菜去买菜.说着说着自己就出门了. 然后,过了大概四五十分钟吧.maqi打电话过来,说..那个那个..你看看我的大衣里面..是不是有我的皮夹子..我忘记带钱包了.. 我立即告诉linyi. linyi非常开心,快快,我也要去超市,我们一起,我迫不及待地要去嘲笑他. maqi是结账的时候才发现没有带钱包的...我说,你必然是被linyi传染的(因为linyi几乎每个星期都会有一次上班时忘记带工卡啊带token啊带钱包啊什么的).linyi很愤慨,那我从来没有到买东西结账的时候才发现没带钱包的... 我们说,其时maqi出门准备得还是很充分的,带了购物袋(我们几乎从来没有带过),还带了手套(拎袋子防止勒手,我们也几乎从来不带).这次经历只有唯一的一点儿败笔,那就是我们每次必定会带的钱包maqi忘记带了. 然后我们就感慨,果然到了新的一年就不一样了.真是岁月不饶人啊,就这么2010到2011年的变化,maqi又老了一岁..然后作为老人,他就... 不过maqi还是很不错地,前几天刚刚买了一箱核桃,补脑啊. 看样子他也是早就预料到会有这一天了. 只是这一天,来得太悄无声息了.

The post n61 岁月 appeared first on 邮递员大叔.

阅读全文>>

Android开发浅谈_Activity数据传递

阅读全文

(原作于2010-05-09) Activity从某种程度上说, 是Android大多数程序的骨架子. 一般很少会有程序只有一个Activity, 因此很多时候, Activity之间的通信和变量传递是非常重要的. Android SDK本身是提供了四种跨进程通讯方式的, 对应了四种应用程序组件: Activity, Content Provider, Broadcast和Service. 在Ophone社区也有对这几种方式的简单说明: Activity可以跨进程调用其他应用程序的Activity(自身应用程序当然也可以); Content Provider可以访问其他应用程序提供的数据, 以Cursor对象形式返回, 也可以进行增删改查操作, 就相当于是对数据库的访问一样; Broadcast可以向所有应用程序发送广播, 进而被”有意者”监听到; Service类似于Content Provider, 不过返回的是Java对象. 我们现在只关注于Activity的通讯. 当我们有如下的xml, 即有两个Activity:

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

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

      package="cn.mishi8"

      android:versionCode="1"

      android:versionName="1.0">

    <application android:icon="@drawable/icon" android:label="@string/app_name">

        <activity android:name=".MainActivity"

                  android:label="@string/app_name">

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

        <activity android:name=".TargetActivity">

        </activity>

    </application>

    <uses-sdk android:minSdkVersion="1" />

</manifest>
我们有这样的需求, 启动MainActivity, 包含一个输入框(EditText)和一个按钮(Button), 输入一个字符串(String)作为名字, 把它传给第二个Activity(Target), 第二个Activity将显示, 从某某处接收到消息, 并在界面上也提供一个按钮(Button), 点击后返回第一个Activity, 告诉它, “我收到你的消息了!” 首先是简单的页面布局, 我们提供两个xml文件, 分别去对应MainActivity和TargetActivity的layout. main.xml:
<?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"

    >

    <EditText

    android:id="@+id/main_edittext1"

    android:layout_width="fill_parent"

    android:layout_height="wrap_content"

    android:hint="@string/main_edittext1">

    </EditText>

    <Button

    android:id="@+id/main_button1"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:text="@string/main_button1">

    </Button>

</LinearLayout>
target.xml:
<?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:id="@+id/target_textview1"

        android:layout_width="fill_parent"

        android:layout_height="wrap_content">

   </TextView>

   <Button

        android:id="@+id/target_button1"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="@string/target_button1">

   </Button>

</LinearLayout>
其中使用”@string”的属性, 自然是需要在string.xml中去注册的. string.xml:
<?xml version="1.0" encoding="utf-8"?>

<resources>

    <string name="hello">Hello World, MainActivity!</string>

    <string name="app_name">第一个Android程序</string>

    <string name="main_edittext1">输入你的名字</string>

    <string name="main_button1">发送消息</string>

    <string name="target_button1">我知道啦</string>

</resources>
下面是MainActivity和TargetActivity两个类的代码, MainActivity:
package cn.mishi8;

import android.app.Activity;

import android.content.Intent;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

public class MainActivity extends Activity {

         private EditText mainEditText1;

         private Button mainButton1;

         private void initView()

         {

                   mainEditText1 = (EditText)findViewById(R.id.main_edittext1);

                   mainButton1 = (Button)findViewById(R.id.main_button1);

         }

         private void initListeners()

         {

                   mainButton1.setOnClickListener(

                            new Button.OnClickListener()

                            {

                                     @Override

                                     public void onClick(View v) {

                                               // TODO Auto-generated method stub

                                               Intent intent = new Intent();

                                               intent.setClass(MainActivity.this, TargetActivity.class);

                                               Bundle bundle = new Bundle();

                                               bundle.putString("name", mainEditText1.getText().toString());

                                               intent.putExtras(bundle);

                                               startActivityForResult(intent, 0);

                                               //by poisonbian

                                               finish();

                                     }

                            }

                   );

         }

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        initView();

        initListeners();

    }

         /* (non-Javadoc)

          * @see android.app.Activity#onActivityResult(int, int, android.content.Intent)

          */

         @Override

         protected void onActivityResult(int requestCode, int resultCode, Intent data) {

                   // TODO Auto-generated method stub

                   switch (resultCode)

                   {

                            case RESULT_OK:

                                     Bundle bundle = data.getExtras();

                                     String result = bundle.getString("result");

                                     mainEditText1.setText(result);

                                     break;

                            default:

                                     break;

                   }

         }

}
TargetActivity:
/**

 *

 */

package cn.mishi8;

import android.app.Activity;

import android.content.Intent;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.TextView;

/**

 * @author poisonbian

 *

 */

public class TargetActivity extends Activity {

         private TextView targetTextView1;

         private Button targetButton1;

         private void initView()

         {

                   targetTextView1 = (TextView)findViewById(R.id.target_textview1);

                   targetButton1 = (Button)findViewById(R.id.target_button1);

                   Bundle bundle = getIntent().getExtras();

                   String name = bundle.getString("name");

                   targetTextView1.setText("收到消息, From: " + name);

         }

         private void initListeners()

         {

                   targetButton1.setOnClickListener(

                            new Button.OnClickListener()

                            {

                                     @Override

                                     public void onClick(View v) {

                                               // TODO Auto-generated method stub

                                               Intent result = new Intent();

                                               result.putExtra("result", "知道啦知道啦~");

                                               setResult(RESULT_OK, result);

                                               finish();

                                     }       

                            }

                   );

         }

         /* (non-Javadoc)

          * @see android.app.Activity#onCreate(android.os.Bundle)

          */

         @Override

         protected void onCreate(Bundle savedInstanceState) {

                   // TODO Auto-generated method stub

                   super.onCreate(savedInstanceState);

                   setContentView(R.layout.target);

                   initView();

                   initListeners();

         }

}
另外, 一定要记得, 在AndroidManifest.xml中去注册两个Activity:
<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

      package="cn.mishi8"

      android:versionCode="1"

      android:versionName="1.0">

    <application android:icon="@drawable/icon" android:label="@string/app_name">

        <activity android:name=".MainActivity"

                  android:label="@string/app_name">

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

        <activity android:name=".TargetActivity">

        </activity>

    </application>

    <uses-sdk android:minSdkVersion="1" />

</manifest>
下面来结合截图看一看, 我们的两个Activity做了什么: MainActivity如下, 它以main.xml为layout: setContentView(R.layout.main); 页面有两个控件, 分别是EditText和Button. Button上有一个Click的Listener, click之后有如下动作:
Intent intent = new Intent();

intent.setClass(MainActivity.this, TargetActivity.class);

Bundle bundle = new Bundle();

bundle.putString("name", mainEditText1.getText().toString());

intent.putExtras(bundle);

startActivityForResult(intent, 0);

//by poisonbian

finish();
新建一个Intent, 源与目标分别为MainActivity与TargetActivity, 新建一个”邮包”Bundle, bundle中放了一个Map, key是”name”, value是mainEditText1中输入的字符串, intent将这个bundle携带在身上, 启动intent(即启动目标Activity), 并且使用的是”startActivityForResult”, 不是”startActivity”, 这表明启动目标Activity是需要等待其返回结果的. 因此这个地方的”finish()”实际是有bug的! 我们不妨先忽略它, 看最终的效果是什么样子. 输入一个字符串, 点击”发送消息”, 跳转到了第二个Activity, 它又做了什么呢? 首先是接收信息:
Bundle bundle = getIntent().getExtras();

String name = bundle.getString("name");

targetTextView1.setText("收到消息, From: " + name);
邮包”bundle”被我们在第二个Activity的Intent中取出来, 然后从里面抽取一个string, 它的key叫做”name”, 对应的value被直接放在了一个TextView中输出. 接下来, 是TargetActivity的Button.
Intent result = new Intent();

result.putExtra("result", "知道啦知道啦~");

setResult(RESULT_OK, result);

finish();
点击后做这样一些事情, 再次声明一个Intent, 它放一个map进去, key为”result”, 然后调用setResult. “RESULT_OK”是Activity的自带变量, 表明这个result的性质, 或者也当做是一个”key”. 然后这个Activity就finish掉了. 再看第一个Activity, 它是想接收到Target的返回信息的. 但是实际上呢? 我们在模拟器中运行, 却会发现, 第二个按了Button之后, 程序全部退出了? 这就是我们刚刚说的那个MainActivity中”finish()”这个语句的bug! 因为启动第二个Activity之后, 自己已经通过finish()结束了, 怎么还能够接收到返回呢? 所以, 这个地方, 如果我们注释掉这句话, 就能够正确地执行以下的语句了:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

                   // TODO Auto-generated method stub

                   switch (resultCode)

                   {

                            case RESULT_OK:

                                     Bundle bundle = data.getExtras();

                                     String result = bundle.getString("result");

                                     mainEditText1.setText(result);

                                     break;

                            default:

                                     break;

                   }

         }
当有结果返回时, 判断resultCode, 如果是RESULT_OK, 那么执行case中对应的语句. 这样的switch就表明, 我们在Target中完全可以构造不同类型的RESULT_*(例如RESULT_CANCELED, 去让源Activity采取不同的操作. 这次对于第一个Activity来说, 它从结果Intent中去获得返回的邮包, 取出”result”, 直接放在EditText中显示, 那么就是如下的效果了:

The post Android开发浅谈_Activity数据传递 appeared first on 邮递员大叔.

阅读全文>>

Android开发浅谈_从HelloAndroid开始

阅读全文

(原作于2010-04-16) 我们在学习一门新的语言时, 习惯于用”HelloWorld”来起步, 这对于程序员来说, 几乎已成为一个”神话”. 那么我们在开始Android学习的时候, 也不放延续一下这”神话”, 跟着我一起来, “Hello, Android!” 上一讲中, 已经成功配置了Android的开发环境.

         首先, 在Eclipse中建立一个Android的工程, 采取以下步骤: File->New->Projects, 选择Android Project, 有如下界面, 填写如下信息

        需要填写的包括项目名称, 应用程序的名称, 包名; 我们这里需要选择编译目标SDK, 传说1.6的SDK目前使用比较广泛, 因此不妨使用它来编译好了. 但是为了支持更多的手机使用, Min SDK Version可以写得更低. 1.6对应的整数版本号是4, 我这里把Min SDK Version设置成了1. 上面会有Warning, 但是可以无视. 最重要的是可以创建一个叫做”Activity”的东西. Activity可以当做是Android中最重要的组成部分之一. 通过Activity, 我们可以产生形形色色的界面, 并在后台实现不同的功能. 大多数Android程序就是由一个又一个的Activity组成的. 当然, 这里不自动生成Activity, 之后也有其他的办法去做这一步.

         Create New Project之后, 可以产生一个New Android Test Project, 但它是可选的. 直接Finish掉也没有任何关系.

         HelloAndroid这个Project已经建好了, 让我们来看一下包结构吧.

        

         来解释一下具体的含义. 首先是default.properties, 这个是Android开发工具自动生成的, 不需要做任何的修改, 当我们以不同版本的模拟器执行项目时, 在这儿会有一个target属性的自动变化.

         AndroidManifest.xml, 这相当于是Android Project的一个入口标识, 支持的SDK版本, Activity, 程序名称, 程序版本, 需要申请的手机执行权限等等, 都在这个地方进行注册. 之前说过, 大部分的Android程序都是由一个个的Activity组成, 在这个地方就需要将各个Activity分别注册好位置以及特定的属性. 例如:

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

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

      package="cn.orzstudio"

      android:versionCode="1"

      android:versionName="1.0">

    <application android:icon="@drawable/icon" android:label="@string/app_name">

        <activity android:name=".MainActivity"

                  android:label="@string/app_name">

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

    </application>

    <uses-sdk android:minSdkVersion="1" />

</manifest>
Package表示主包名, versionCode表示内部版本号, 只能是数字. 这个就能够识别不同版本的程序, 例如旧版本已经安装, 重新安装更新的版本(versionCode更大), 就可以使用”upgrade”的安装方式, 避免了卸载和数据丢失. versionName可以是数字以外的字符串, 一般可以定义为1.0, 1.1, 1.2这样的. Application这个tag中设置了icon(图标), label(程序名称), 但是你应该也注意到了, 这里面用到了@drawable和@string这样的格式. 这个和后面的activity定义中的@string/app_name是一样的. @drawable表示图标会使用drawable文件夹下的icon.png这个文件, @string表示会从values/strings.xml这个文件里面去读取app_name这个值. 例如strings.xml的样例是:
<?xml version="1.0" encoding="utf-8"?>

<resources>

    <string name="hello">Hello World, MainActivity!</string>

    <string name="app_name">第一个Android程序</string>

</resources>
凡是其中定义的string, 都可以在AndroidManifest.xml以及layout下面的样式xml文件中使用.

         回过头来继续看AndroidManifest.xml文件, 其中定义了MainActivity这个activity, 它内嵌了这样的标志:

<intent-filter>

                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>
这就表示, 这是我们整个程序启动后, 第一个进入的Activity.

Drawable-*dpi这几个文件夹, 是1.6中支持的形式, 可以定义多种分辨率下使用不同的图标. 为了兼容更旧的版本(1.1, 1.5), 我们可以将这三个文件夹去掉, 只是用drawable一个文件夹, 其中放上一个48*48的icon文件.

Layout文件夹中可以定义各种显示效果, 定义好了之后再与Activity关联, 我们暂时跳过它, 不是它不重要, 而是它太重要了, 每个新的Activity, 每种不同显示效果的Activity, 都需要有不同的xml样式文件来支持, 甚至有时缺少了一些属性也会造成开发出来的程序的强制退出.

Gen这个文件夹, 叫做Generated Java Files, 顾名思义, 是自动生成的, 这有ide帮我们操作, 不需要太多操心. 例如我们在strings.xml中定义的字符串, 在layout中定义的xml layout, 都会被分配一个独特的id标识, 通过gen下的cn.orzstudio文件夹下的R.java来在程序中进行调用.

Src下, 自然是我们放置程序的地方.

现在已经自动建立了一个叫做MainActivity.java的文件, 让我们来简单看一下.

果然非常简单. 代码如下:

package cn.orzstudio;

import android.app.Activity;

import android.os.Bundle;

public class MainActivity extends Activity {

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

    }

}
所有的自定义Activity都需要继承Activity这个父类, 当然, 也有一些其他的Activity的子类可以替代, 并且会增加一些更加定制性的功能. 这个我们也留作后话.

在Eclipse中安装了Android开发插件后会有这么一个图标(下图中的小机器人).

 

点击它可以管理模拟器,

New中可以创建不同版本的模拟器, 只要你的SDK路径下包含有对应的版本开发包, 就可以建立这个版本的模拟器. 我们开发时也主要可以采用1.6的模拟器, 与SDK也对应起来.

任意取一个Name, Target中选择Android 1.6 – API Level 4. SD Card可以使用之前我们已经创建好的那个img文件. Skin选择默认. Hardware暂时也选择默认好了.

右击HelloAndroid的Project图标, 选择Run As -> Android Application, 点击选择Launch a new Android Virtual Device, 下面选择一个合适版本的模拟器, 点OK, 耐心等待.

 

恭喜你, HelloAndroid成功!

The post Android开发浅谈_从HelloAndroid开始 appeared first on 邮递员大叔.

阅读全文>>

Android开发浅谈_环境准备

阅读全文

(原作于2010-03-19) 虽然很不情愿, 但是总归还是要讲这个恶心的”环境准备”的, 而且我也不需要再讲什么”工欲善其事必先利其器”之类的道理. 作为程序员, 我们都该知道, 开发环境的准备, 总归会是一个体力活儿. 我这儿用的是Windows xp系统, 对于瘟到死新版(喂死它或者瘟漆), 可能会对Eclipse的版本有更高的版本要求, 关于这一点, 在下载之前确认可以使用就行了. 废话不多说, 我们来一步步地操作.

  1. 明确自己需要的开发环境.
Android是Google的”原版”系统, 中移动在引进了Android之后, 又增加了一些新的定制性函数功能, 提供了新的手机模拟器等, 称作Ophone. 从用户量上来看, 自然还是纯Android更加广大一些, 而且理论上(又是这个可恶的”理论上”) Ophone的手机是可以兼容Android程序的, 毕竟我们可以理解为: Android包含于Ophone. 我的开发都是基于Android自己的SDK, 后来为了以防万一, 在发布程序的时候还是用了Ophone和Android两套SDK, 分别编译得到了apk程序包. 这一点在以后再加以说明.
  1. JDK的准备
Android是基于Java的, 这个我们已经说过了, 所以对于Android开发者而言, 在部署Android所需要的SDK前, 自然就需要一套Java程序能够跑起来的环境. 这些对于Java的开发者就是多余的了, 如果你的机器上还没有安装JDK也没有关系, 只需要到http://java.sun.com/javase/downloads/widget/jdk6.jsp 就能够下载到最新的JDK+JRE. 似乎是需要注册和登录的, 不过这些都不会成为我们环境搭建的障碍.
  1. Eclipse: IDE的安装和常用的插件
说起Eclipse想必大家也都很熟悉, 实在是没有太大的必要去再花上一笔力气去讲它. 想推荐些常用的插件. 一个是Lomboz, 虽然对于开发Android程序并没有什么作用, 但是Lomboz作为一款集成了多个常用插件的Eclipse”定制版”IDE, 确实是非常好用的, 在平时开发java, jsp等非常有用. 还有一个是SVN插件: Subclipse(http://subclipse.tigris.org/update), 这对于我们管理软件的开发过程非常有帮助, 能够有效帮助我们减少故障恢复的时间. 与之配合, 我们需要安装一个SVN server, 我在用的是Visual SVN, 用起来非常简单. 下载地址http://dl.pconline.com.cn/download/58129.html
  1. 安装Android所需要的SDK和Eclipse插件
好了, 下面开始进入Android相关环节了. 首先是下载Android的SDK, 如果你看过我写的前传, 想必对我对于SDK的碎碎念还有些印象. 诸位可以从http://download.pchome.net/development/sample/detail-142455.html这个地方下载最新的2.1SDK, 但是这并不包含ADB tools等, 即只是单纯的api提供者, 并没有调试用的模拟器等. SDK下载到了, 模拟器怎么办呢, 幸好我有很久以前下载下来的1.5版本的SDK, 里面也放了模拟器和升级器, 现在可以从 http://dl.google.com/android/android-sdk-windows-1.5_r3.zip这个地方下载, 可能会慢一些, 但是好歹用迅雷慢慢拖着可以下载到. 之前下载的2.1版本解压缩之后, 放到1.5版本下的platforms文件夹下就可以了. 但是现在还有一个问题, 1.5对应的模拟器又老了. 那么不妨再运行1.5这个文件夹底下的SDK setup程序, 它可以帮助你去同步服务器上的版本, 这个时候记住千万别贪心, 想把所有版本的SDK, Doc文档之类都下载到, 老老实实地选择最高版本(7)对应的模拟器(platform)吧. 经过龟速的下载之后, 我们终于得到了来之不易的Android开发包. 但还没有结束, 我们还有一个重要的步骤, 那就是添加Eclipse中的插件. 这里只需要记住这个下载地址: https://dl-ssl.google.com/android/eclipse/ 按照正常的Eclipse安装插件步骤进行就可以了(Help -> Software Updates -> Find and install -> Search for new features to install -> New Remote Site ->blabla) 再之后, 在Eclipse的菜单里再做一下简单的设置, Window -> Preferences, Android里选择SDK的路径, Apply一下就OK了. 现在Android的开发环境的确可以使用了, 不过我们在真正的开发中往往需要对SD卡进行操作, ADB也是可以设置SD卡的虚拟的. 只需要以下步骤: 运行dos, 进入SDK安装目录的tools文件夹下, 运行mksdcard 128M D:\sdcard.img (分别是表示sd卡的大小和路径). 然后在Eclipse的Android设置中Launch里的默认参数中输入-sdcard d:\sdcard.img, 表示在Launch虚拟机时默认加载这样一个SD卡. 这样才算是大功告成, 功德圆满. 请珍惜这来之不易的编程环境, 如果有必要, 不妨整个环境做成个ISO刻一张盘, 挂在门口, 又可备份, 又可辟邪.   环境准备至此结束, 之前也没有料到会花将近1500个字来写这一步. 不过还好, 下篇文章, 我们就将进入Android的世界, 一起”Hello Android”!  

The post Android开发浅谈_环境准备 appeared first on 邮递员大叔.

阅读全文>>