利用Ant脚本实现Android项目自动批量打包
因为Android项目加入了有盟统计,每次升级都需要单独针对每一个market或论坛打一个apk,这样当渠道变得越来越多时,打包就变成了一件相当繁琐的事情。
其实可以用Ant脚本来实现自动批量打包:
一、为Android项目增加自定义Ant支持:
这里有一篇非常不错的介绍说明:Using Ant to Automate Building Android Applications
不过有一点不太准确:android_rules模板文件,应该采用android-sdk-windows\tools\ant\main_rules.xml,文章中的android_rules.xml 或 ant_rules_r#.xml都有问题。
二、在build.xml中增加如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <taskdef resource="net/sf/antcontrib/antcontrib.properties"> <classpath> <pathelement location="lib/ant-contrib-1.0b3.jar"/> </classpath> </taskdef> <target name="deploy"> <foreach target="modify_manifest" list="${market_channels}" param="channel" delimiter=","> </foreach> </target> <target name="modify_manifest"> <replaceregexp flags="g" byline="false"> <regexp pattern="android:value="(.*)" android:name="UMENG_CHANNEL"" /> <substitution expression="android:value="${channel}" android:name="UMENG_CHANNEL"" /> <fileset dir="" includes="AndroidManifest.xml" /> </replaceregexp> <property name="out.release.file" location="${out.absolute.dir}/${ant.project.name}_${channel}_${app_version}.apk" /> <antcall target="release" /> </target> |
taskdef 声明需要放到较前位置,因为if condition也会用到此声明。
build.properties文件增加:
1 2 | market_channels=UMENG,XIANGUO,MARKET,HIAPK,GOAPK app_version=1.2.1 |
market名称用逗号分隔
初学者如何学习Android
这是我在知乎上的回答:http://www.zhihu.com/question/19611325
http://stackoverflow.com/
初期遇到的问题,stackoverflow总能找到。
http://stackoverflow.com/questions/tagged/android?sort=votes
投票最多的几个问题,空闲时看看。
SDK文档:建议除Reference以外,全部看一遍。
订阅几个不错的博客:
http://blog.csdn.net/Android_Tutor/
http://www.helloandroid.com/
http://www.poemcode.net
http://android-developers.blogspot.com/
http://blog.csdn.net/hellogv
http://flyvenus.net/
加入邮件列表:
http://groups.google.com/group/china-android-dev/
http://groups.google.com/group/android-developers/
定期去SlideShare找些ppt看,下载到ipad上看很爽。
http://www.slideshare.net/search/slideshow?q=android/
阅读源码:
http://android.git.kernel.org/
http://code.google.com/p/apps-for-android/
http://code.google.com/p/iosched/
https://github.com/kaeppler/droid-fu 网络图片下载及缓存
WebView宽度自适应
用WebView组件显示普通网页时一般会出现横向滚动条,这样会导致页面查看起来非常不方便。其实通过设置WebSettings的属性可以轻易地解决此问题,不过此设置隐藏的比较深,一般很少人会用到。
1 2 | webSettings= webView.getSettings(); webSettings.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); |
LayoutAlgorithm是一个枚举,用来控制html的布局,总共有三种类型:
NORMAL:正常显示,没有渲染变化。
SINGLE_COLUMN:把所有内容放到WebView组件等宽的一列中。
NARROW_COLUMNS:可能的话,使所有列的宽度不超过屏幕宽度。
如何改变Android Progressbar默认颜色
默认情况下Indeterminate Progressbar是白色的,如果容器的背景也是白色的,这样就根本看不到Progressbar了。
幸好Android自带了一些反转样式,你可以采用其中一个合适的:
1 2 3 | <ProgressBar style="@android:style/Widget.ProgressBar.Inverse"/> <ProgressBar style="@android:style/Widget.ProgressBar.Large.Inverse"/> <ProgressBar style="@android:style/Widget.ProgressBar.Small.Inverse"/> |
转自:http://stackoverflow.com/questions/2638161/how-to-change-android-indeterminate-progressbar-color
Android Instapaper Client
自从转战Android以后,就计划做一个Instapaper客户端作为练手项目,还不知道Instapaper是啥玩意?参见对Instapaper创始人的一篇访谈。
年假期间终于有空完成了1.0版本,目前可以自动同步Instapaper上全部文章,并且支持离线阅读。
附几张截图:
可以在market上搜索“Instapaper Client”进行下载,也可以用手机扫描下面二维码获取下载地址:
Android自动弹出软键盘
在AndroidManifest.xml文件,对应Activity处增加:android:windowSoftInputMode=”stateVisible|adjustResize”
stateVisible:打开Activity时自动弹出软键盘
adjustResize:Acitivity根据屏幕中的软键盘而调整大小,可以让软键盘始终显示在屏幕下方,并且不会将操作按钮覆盖住。
参照:http://developer.android.com/guide/topics/manifest/activity-element.html#wsoft
修改TabHost默认样式
TabHost是Android提供的一个容器组件,利用它可以轻松地实现TAB界面,如下图所示:
但很多时候,默认的TAB样式并不符合软件的整体风格,这时候该怎么办呢?其实,我们可以编写XML对其样式进行修改。下面修改后的效果图:
1. TabHost布局文件 main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | <TabHost android:id="@+id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TabWidget android:id="@android:id/tabs" android:layout_width="fill_parent" android:layout_height="30dip" android:background="#a0a0a0" android:layout_weight="0" /> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1"> <ListView android:id="@+id/user_list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:divider="@drawable/divider_line" android:cacheColorHint="#00000000" /> <ListView android:id="@+id/article_list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:divider="@drawable/divider_line" android:cacheColorHint="#00000000" /> <ListView android:id="@+id/feed_list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:divider="@drawable/divider_line" android:cacheColorHint="#00000000" /> <ListView android:id="@+id/book_list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:divider="@drawable/divider_line" android:cacheColorHint="#00000000" /> </FrameLayout> </LinearLayout> </TabHost> |
FrameLayout里有四个ListView 分别对应用户、文章、频道、图书。
TabWidget和FrameLayout的ID不能自己定义修改。
2. Activity后台代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | RelativeLayout articleTab = (RelativeLayout) LayoutInflater.from(this).inflate(R.layout.minitab, null); TextView articleTabLabel = (TextView) articleTab.findViewById(R.id.tab_label); articleTabLabel.setText("文章"); RelativeLayout feedTab = (RelativeLayout) LayoutInflater.from(this).inflate(R.layout.minitab, null); TextView feedTabLabel = (TextView) feedTab.findViewById(R.id.tab_label); feedTabLabel.setText("频道"); RelativeLayout bookTab = (RelativeLayout) LayoutInflater.from(this).inflate(R.layout.minitab, null); TextView bookTabLabel = (TextView) bookTab.findViewById(R.id.tab_label); bookTabLabel.setText("图书"); TabHost tabHost = (TabHost) findViewById(R.id.tabhost); tabHost.setup(); tabHost.addTab(tabHost.newTabSpec("user").setIndicator(userTab).setContent(R.id.user_list)); tabHost.addTab(tabHost.newTabSpec("article").setIndicator(articleTab).setContent(R.id.article_list)); tabHost.addTab(tabHost.newTabSpec("feed").setIndicator(feedTab).setContent(R.id.feed_list)); tabHost.addTab(tabHost.newTabSpec("book").setIndicator(bookTab).setContent(R.id.book_list)); |
TabHost创建出来以后,必须先setup一下,tabHost.setup();
setIndicator方法设置的View其实就对应了TAB中的一个个选项卡,它们都是通过一个叫minitab的布局文件inflate出来的。
3. 选项卡布局文件minitab.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:paddingLeft="5dip" android:paddingRight="5dip"> <TextView android:id="@+id/tab_label" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" android:textColor="#000000" android:textStyle="bold" android:background="@drawable/minitab" /> </RelativeLayout> |
drawable/minitab是一个selector,指定了Tab选项卡的背景颜色。
4. selector文件 minitab.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" > <item android:state_selected="false" android:drawable="@drawable/minitab_unselected" > </item> <item android:state_selected="true" android:drawable="@drawable/minitab_default" > </item> </selector> |
minitab_unselected是一浅蓝色背景图片
minitab_default是一白色背景图片
Android分享功能
代码如下:
1 2 3 4 5 | Intent intent=new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_SUBJECT, "分享"); intent.putExtra(Intent.EXTRA_TEXT,"I would like to share this with you..."); startActivity(Intent.createChooser(intent, getTitle())); |
Android View Hierarchy
Hierarchy Viewer 是Android SDK里的一个工具,可以帮助你分析应用程序的UI布局。
使用方式:
- 连接移动设备或打开模拟器。
- 运行 hierarchyviewer,具体路径:android-sdk-windows\tools\hierarchyviewer.bat。
- 选择设备,点击[load View Hierarchy]按钮,就可以捕获到当前activity的布局信息。
- 双击树节点可以展示单独的UI部分。






