1 2012

密码保护:如何去掉Android App里的内置广告

这是一篇受密码保护的文章。您需要提供访问密码:



25 2011

利用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=&quot;(.*)&quot; android:name=&quot;UMENG_CHANNEL&quot;" />
	<substitution expression="android:value=&quot;${channel}&quot; android:name=&quot;UMENG_CHANNEL&quot;" />
	<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名称用逗号分隔

执行ant deploy会自动在项目bin目录下生成如下apk文件:


18 2011

初学者如何学习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 网络图片下载及缓存


18 2011

WebView宽度自适应

用WebView组件显示普通网页时一般会出现横向滚动条,这样会导致页面查看起来非常不方便。其实通过设置WebSettings的属性可以轻易地解决此问题,不过此设置隐藏的比较深,一般很少人会用到。

1
2
webSettings= webView.getSettings();
webSettings.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);

LayoutAlgorithm是一个枚举,用来控制html的布局,总共有三种类型:
NORMAL:正常显示,没有渲染变化。
SINGLE_COLUMN:把所有内容放到WebView组件等宽的一列中。
NARROW_COLUMNS:可能的话,使所有列的宽度不超过屏幕宽度。


18 2011

如何改变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


31 2011

Android Instapaper Client

自从转战Android以后,就计划做一个Instapaper客户端作为练手项目,还不知道Instapaper是啥玩意?参见对Instapaper创始人的一篇访谈

年假期间终于有空完成了1.0版本,目前可以自动同步Instapaper上全部文章,并且支持离线阅读。

附几张截图:

可以在market上搜索“Instapaper Client”进行下载,也可以用手机扫描下面二维码获取下载地址:

market://details?id=org.hijava.instapaper


十二 25 2010

Android自动弹出软键盘

在AndroidManifest.xml文件,对应Activity处增加:android:windowSoftInputMode=”stateVisible|adjustResize”

stateVisible:打开Activity时自动弹出软键盘
adjustResize:Acitivity根据屏幕中的软键盘而调整大小,可以让软键盘始终显示在屏幕下方,并且不会将操作按钮覆盖住。

参照:http://developer.android.com/guide/topics/manifest/activity-element.html#wsoft


十二 25 2010

修改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是一白色背景图片


十二 18 2010

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()));

十二 6 2010

Android View Hierarchy

Hierarchy Viewer 是Android SDK里的一个工具,可以帮助你分析应用程序的UI布局。

使用方式:

  1. 连接移动设备或打开模拟器。
  2. 运行 hierarchyviewer,具体路径:android-sdk-windows\tools\hierarchyviewer.bat。
  3. 选择设备,点击[load View Hierarchy]按钮,就可以捕获到当前activity的布局信息。
  4. 双击树节点可以展示单独的UI部分。