最近公司组织进行无线开发大赛,旨在提升团队的无线开发能力,还有大奖呵呵,抱着学习的态度,也没想拿奖,就一个人报名了,服务端和客户端自己搞定,作为服务端开发经验丰富,一天多的时间就搞定了,但是android的开发花了很多时间,中间有很多坑,最后也算能够交差了。
开发环境搭建就不写了,网上资料很多,大致就是下载android 的SDK,添加android开发的eclipse插件,然后eclipse中关联SDK,就OK了。
(1)请求http接口,网络权限问题
这是遇到的第一个问题,之前纳闷android是如何发起网络请求的,搜了些文章发现原来是通过httpclient,然后写好httpclient代码,但是请求不到服务端,找了半天,原始是android的这个文件AndroidManifest.xml,需要开通权限。
在android中通过Httpclient请求外部的服务是,会报这个错误java.net.UnknownHostException,原因是代码中没有设置访问网络的权限,在AndroidManifest.xml中添加这个配置即可 <uses-permission android:name="android.permission.INTERNET"/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
List<BasicNameValuePair> params =
new
LinkedList<BasicNameValuePair>();
params.add(
new
BasicNameValuePair(
"userId"
, String.valueOf(userId)));
params.add(
new
BasicNameValuePair(
"dateId"
, String.valueOf(dateId)));
String param = URLEncodedUtils.format(params,
"UTF-8"
);
//这个大家都懂,添加参数
HttpClient client = HttpClientUtil.getHttpClient();
HttpGet get =
new
HttpGet(AppConstant.DOMAIN+param);
HttpResponse response = client.execute(get);
BufferedReader reader =
null
;
HttpEntity entity = response.getEntity();
reader =
new
BufferedReader(
new
InputStreamReader(entity.getContent(),
"gbk"
));
//获取Content,然后创建stream
StringBuilder sb =
new
StringBuilder();
for
(String s = reader.readLine(); s !=
null
; s = reader.readLine()) {
sb.append(s);
}
|
(2)activity没有熟悉例子,只是想到啥就做啥
在做产品规划的时候,没有设计,自己想到啥就去做啥了,页面也是这样,基本上想到啥样就去调整了, 现在想来,这是一个失误,应该把之前android支持的组件先熟悉一遍,能够做到灵活运用,这样就好了。。。
(3)依赖外部的jar包,如何打入到apk中
android中如果要添加外部的jar包,需要把jar包拷到libs目录下面,否则如果仅仅关联了classpath,那样运行在模拟机上的话会报错,java.lang.NoClassDefFoundError这个异常。当时怀疑,android项目是这样来添加jar包的?岂不是很低级?升级一次jar包会是一件头疼的事情,然后网上找了一下,maven官方没有提供工具,android也没有,但是开源有个插件 maven-android-plugin,能够把android构建成maven项目,这样添加jar包,导入apk文件,是一件很容易的事情。
(4)MTOP怎么使用(MTOP 一淘无线团队的开放平台,提供了复用的组件)
app中有个淘宝账号登陆的功能,当时觉得麻烦,打算复用一淘无线团队中的组件,了解了半天,发现接入起来太费劲,要申请一些列东西,就放弃了。但是了解的这个过程还是有收获,后续开发,尽量把公共功能组件化,减少开发成本,然后api接口的话设计灵活巧妙。
(5)关于退出app
关于应用退出这个功能,自己在使用app的时候,比较喜欢按两次back键来完成退出,然后打算自己在功能中实现这个。在晚上找了一下,基本上是这种代码,说的比较简单,“监听back事件,然后把activity状态变为finish”,
但是在写完代码后遇到一个问题,就是只能退出当前的activity,连续双击后,展示出了这个activity的上一个activity,这个有点体验不好,然后继续找资料,最后的解决方案。
A、搞了一个父类,继承Activity,然后其他自定义的Activity实现这个基类,基类中重写onCreate这个方法;
B、在onCreate方法中,构造单例,把当前的Activity对象添加到列表中;
1
2
3
4
|
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
ActivityList.getInstance().addActivity(
this
);
}
|
C、然后在父类中监听onBackPressed这个事件,就是点击“back”的操作;
D、符合退出条件的情况下,在单例中,把存储在列表中的activity对象依次finish,这样就实现退出了;
1
2
3
4
5
6
7
8
9
10
11
12
13
|
long
waitTime =
2000
;
long
touchTime =
0
;
//监听后退按键
@Override
public
void
onBackPressed() {
long
currentTime = System.currentTimeMillis();
if
((currentTime-touchTime)>=waitTime) {
Toast.makeText(
this
,
"哈哈,再按一次,就退出瞄过往了"
, Toast.LENGTH_SHORT).show();
touchTime = currentTime;
}
else
{
ActivityList.getInstance().exit();
}
}
|
(6)handle机制
在App中有种情况,就是请求网络中的数据,这一步是很耗时的,所以就想异步来做,自己就new Thread来请求数据,把数据放到缓存中,但是有个问题,就是需要搞一个“加载中”的提示,当时以为很简单,在new出来的线程中调用了一下ProgressBar的消失方法,但是运行的时候抛出异常,说是不能new线程,但是反复试了很多办法,但是没有解决。
此时,就想把加载数据改成同步,这样就不会有问题了,但是试了一下,在等待网络请求的时候,超过5秒的时间,android就会弹出层,说是系统没响应,是否要强制关闭。
于是有开始想办法,此时找到了这篇文章:http://www.pin5i.com/showtopic-android-handler.html
原来关于Activity的相关UI操作,只能由主线程来进行(因为是非线程安全的)。Handler就出现了,来解决这个复杂的问题 , 由于Handler运行在主线程中(UI线程中), 它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据) , 把这些消息放入主线程队列中,配合主线程进行更新UI。
继承Handle类:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class
MyHandler
extends
Handler {
public
MyHandler() {
}
public
MyHandler(Looper L) {
super
(L);
}
// 子类必须重写此方法,接受数据
@Override
public
void
handleMessage(Message msg) {
super
.handleMessage(msg);
MainActivity.
this
.dialog.dismiss();
}
}
|
然后在异步线程中调用Handle来传递数据,完成UI的变化:MainActivity.this.handle.handleMessage(null);
(7)android中的异步
在这次APP中,异步的任务是通过new Thread的方式来进行的,虽然问题解决了,但是觉得有点山寨,搜了一下,发现android中提供了方案AsyncTask来满足这个需求。
子类必须实现AsyncTask中的doInBackground(Params...)这个方法。
AsynTask类在继承时要传入3个泛型。第一个泛型对应execute()向doInBackground()的传递类型。第二个泛型对应doInBackground()的返回类型和传递给onPostExecute()的类型。第三个泛型对应publishProgress()向progressUpdate()传递的类型,这个是用来通知主线程,例如数据加载进度等。
(8)数据的埋点
这次app中,为了了解用户的使用情况,在友盟哪里找了个工具,把系统的埋点做了下,在Activity中,有各个状态,resume和pause,然后在父类中添加埋点,剩下的事情交给友盟去做了,然后既可以在友盟提供的页面上看到数据了。友盟获取机器的UMID信息后,然后结合配置文件中的appkey,既可以定位唯一的一台机器,然后结合埋点数据,分析出结果,个人觉得很好用,接入一个小时就够了。
1
2
3
4
5
6
7
8
|
public
void
onResume() {
super
.onResume();
MobclickAgent.onResume(
this
);
}
public
void
onPause() {
super
.onPause();
MobclickAgent.onPause(
this
);
}
|