分类归档 Android

通过admin

Java protobuf框架使用向导

 

ProtoBuf,全称是Protocol Buffers, 它是谷歌内部用的一种高效的、可扩展的对结构化数据进行编码的格式规范。谷歌自己内部很多程序之间的通信协议都用了ProtoBuf。

下面介绍的是使用Java ProtoBuf的基本步骤:

1.http://code.google.com/p/protobuf/downloads/list ,选择其中的win版本下载

2.下载一个protobuf-java-2.4.1.jar文件(注意,要与你刚才下的proto.exe版本相同,否则可能出现编译通不过现象)

http://grepcode.com/snapshot/repo1.maven.org/maven2/com.google.protobuf/protobuf-java/2.4.1

3.在proto.exe同级目录,编写一个msg.proto文件:

 

package tutorial;

 

option java_package = “com.protobuftest.protobuf”;

option java_outer_classname = “PersonProbuf”;

 

message Person {

required string name = 1;

required int32 id = 2;

optional string email = 3;

 

enum PhoneType {

MOBILE = 0;

HOME = 1;

WORK = 2;

}

 

message PhoneNumber {

required string number = 1;

optional PhoneType type = 2 [default = HOME];

}

 

repeated PhoneNumber phone = 4;

 

message CountryInfo {

required string name = 1;

required string code = 2;

optional int32 number = 3;

}

}

 

message AddressBook {

repeated Person person = 1;

}

 

4.使用如下命令编译这个文件:

5.将生成的ProtoBufferPractice.java文件引入eclipse

6.把下载的protobuf-java-2.4.1.jar也引入工程

7.使用方法:

package com.protobuftest;

 

import java.util.List;

 

import com.google.protobuf.InvalidProtocolBufferException;

import com.protobuftest.protobuf.PersonProbuf;

import com.protobuftest.protobuf.PersonProbuf.Person;

import com.protobuftest.protobuf.PersonProbuf.Person.PhoneNumber;

import com.protobuftest.protobuf.PersonProbuf.Person.PhoneNumberOrBuilder;

import com.protobuftest.protobuf.PersonProbuf.Person.PhoneType;

 

public class ProtoBufTest {

 

/**

* @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

PersonProbuf.Person.Builder builder = PersonProbuf.Person.newBuilder();

builder.setEmail(“kkk@email.com”);

builder.setId(1);

builder.setName(“TestName”);

builder.addPhone(PersonProbuf.Person.PhoneNumber.newBuilder().setNumber(“131111111”).setType(PersonProbuf.Person.PhoneType.MOBILE));

builder.addPhone(PersonProbuf.Person.PhoneNumber.newBuilder().setNumber(“011111”).setType(PersonProbuf.Person.PhoneType.HOME));

 

Person person = builder.build();

byte[] buf = person.toByteArray();

 

try {

Person person2 = PersonProbuf.Person.parseFrom(buf);

System.out.println(person2.getName() + “, ” + person2.getEmail());

List<PhoneNumber> lstPhones = person2.getPhoneList();

for (PhoneNumber phoneNumber : lstPhones) {

System.out.println(phoneNumber.getNumber());

}

} catch (InvalidProtocolBufferException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

System.out.println(buf);

 

}

 

}

 

源文档 <http://blog.csdn.net/csharp25/article/details/6632127>

通过admin

Android日期时间格式国际化

在做多语言版本的时候,日期时间的格式话是一个很头疼的事情,幸好Android提供了DateFormate,可以根据指定的语言区域的默认格式来格式化。直接贴代码:

public static CharSequence formatTimeInListForOverSeaUser(

final Context context, final long time, final boolean simple,

Locale locale) {

final GregorianCalendar now = new GregorianCalendar();

 

// special time

if (time < MILLSECONDS_OF_HOUR) {

return “”;

}

 

// today

final GregorianCalendar today = new GregorianCalendar(

now.get(GregorianCalendar.YEAR),

now.get(GregorianCalendar.MONTH),

now.get(GregorianCalendar.DAY_OF_MONTH));

final long in24h = time – today.getTimeInMillis();

if (in24h > 0 && in24h <= MILLSECONDS_OF_DAY) {

java.text.DateFormat df = java.text.DateFormat.getTimeInstance(

java.text.DateFormat.SHORT, locale);

return “” + df.format(time);

}

 

// yesterday

final long in48h = time – today.getTimeInMillis() + MILLSECONDS_OF_DAY;

if (in48h > 0 && in48h <= MILLSECONDS_OF_DAY) {

return simple ? context.getString(R.string.fmt_pre_yesterday)

: context.getString(R.string.fmt_pre_yesterday)

+ ” ”

+ java.text.DateFormat.getTimeInstance(

java.text.DateFormat.SHORT, locale).format(

time);

}

 

final GregorianCalendar target = new GregorianCalendar();

target.setTimeInMillis(time);

 

// same week

if (now.get(GregorianCalendar.YEAR) == target

.get(GregorianCalendar.YEAR)

&& now.get(GregorianCalendar.WEEK_OF_YEAR) == target

.get(GregorianCalendar.WEEK_OF_YEAR)) {

java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(“E”, locale);

final String dow = “” + sdf.format(time);

return simple ? dow : dow

+ java.text.DateFormat.getTimeInstance(

java.text.DateFormat.SHORT, locale).format(time);

}

 

// same year

if (now.get(GregorianCalendar.YEAR) == target

.get(GregorianCalendar.YEAR)) {

return simple ? java.text.DateFormat.getDateInstance(

java.text.DateFormat.SHORT, locale).format(time)

: java.text.DateFormat.getDateTimeInstance(

java.text.DateFormat.SHORT,

java.text.DateFormat.SHORT, locale).format(time);

}

 

return simple ? java.text.DateFormat.getDateInstance(

java.text.DateFormat.SHORT, locale).format(time)

: java.text.DateFormat.getDateTimeInstance(

java.text.DateFormat.SHORT, java.text.DateFormat.SHORT,

locale).format(time);

}

 

注意这里用的是java.text.DateFormat,还有另外一个java.text.format.DateFormat,后者不能指定locale。

详细介绍见:http://developer.android.com/reference/java/text/DateFormat.html

通过admin

Android中string.xml使用总结

<b></b>加粗字体

 

<i></i> 斜体字体

 

<u></u> 给字体加下划线

 

\n 换行

 

\u0020表示空格

 

\u2026表示省略号

 

使用&lt;b>和&lt;b>来打印出<b></b> 这样的文字;“&lt;”表示“<”的意思;

 

使用textView.setText(Html.fromHtml(“Hello <b>World</b>,<font size=\”3\” color=\”red\”>AnalysisXmlActivty!</font>”));设置类似于html那样的效果

 

如果你需要使用 String.format(String, Object…) 来格式化你的字符串,你可以把格式化参数放在你的字符串中,参见下面的例子:

 

<string name=”welcome_messages”>Hello, %1$s! You have %2$d new messages.</string>

 

在这个例子中,这个格式化的字符串有2个参数, %1$s是个字符串 %2$d 是个浮点数,你可以在你的程序中按照下面的方法来根据参数来格式化字符串:

 

Resources res = getResources();

 

String text = String.format(res.getString(R.string.welcome_messages), username, mailCount);

 

那么根据例子上说的我需要把%s换成%1$s才行了,修改后编译通过,程序成功启动。

 

问题补充:如何在<string></string>中使用%号

 

有两个办法可供选择

1.用%%来表示1个%,和转意符号 \ 的用法相同

 

2.如果你的字符串不需要格式化,可以在你的<string 标签上增加一个属性:formatted=”false”例如 <string name=”test” formatted=”false”>% test %</string> 即可

通过admin

Update plug-in ant from 1.7 to 1.8

如果不更新1.8,会报以下的错误:

The Android Ant-based build system requires Ant 1.8.0 or later. Current version is 1.7.1…

1)到网站(http://ant.apache.org/)下载Ant的目前最新的版本1.8

2)下载解压到本地的一个目录, 如 /opt/apache-ant-1.8.2

3)打开eclipse->Preferences->Ant->Runtime

删除 Ant Home Entries下关于1.7的所有选项,

然后 点击 Ant Home ,点位到已经解压出来的ant( /opt/apache-ant-1.8.2)

一次点击确定/OK 即可。

 

转自:http://www.cnblogs.com/mengshu-lbq/archive/2011/03/24/1993764.html

通过admin

在Android中支持表情

最近项目需要支持表情,表情的添加和解析实现基本上是参照Android自身的SmileyParser,具体就不多讲了,直接贴上代码:
public class SmileyParser {
private static SmileyParser sInstance = null;

private Context mContext = null;
private Pattern mPattern = null;
private HashMap<String, Integer> mSmileyTextToId = null;
private final String[] mSmileyArrays =
{“/西瓜”,”89″,”/便便”,”59″,”/太陽”,”74″,”/偷笑”,”20″,”/傲慢”,”23″,”/再見”,”39″,”/凋謝”,”64″,”/發呆”,”3″,”/發怒”,”11″,”/閃電”,”54″,”/可愛”,”21″,”/豬頭”,”46″,”/咖啡”,”60″,”/哈欠”,”104″,”/鄙視”,”105″,”/委屈”,”106″,”/快哭了”,”107″,”/陰險”,”108″,”/親親”,”109″,”/嚇”,”110″,”/可憐”,”111″,”/菜刀”,”112″,”/啤酒”,”113″,”/籃球”,”114″,”/乒乓”,”115″,”/示愛”,”116″,”/瓢蟲”,”117″,”/抱拳”,”118″,”/勾引”,”119″,”/拳頭”,”120″,”/差勁”,”121″,”/愛你”,”122″,”/NO”,”123″,”/OK”,”124″,”/轉圈”,”125″,”/磕頭”,”126″,”/回頭”,”127″,”/跳繩”,”128″,”/揮手”,”129″,”/激動”,”130″,”/街舞”,”131″,”/獻吻”,”132″,”/左太極”,”133″,”/右太極”,”134″,”/吐”,”19″,”/蛋糕”,”53″,”/呲牙”,”13″,”/咒罵”,”31″,”/足球”,”57″,”/嘘”,”33″,”/困”,”25″,”/大兵”,”29″,”/大哭”,”9″,”/强”,”76″,”/奮鬥”,”30″,”/擁抱”,”49″,”/害羞”,”6″,”/尷尬”,”10″,”/右哼哼”,”103″,”/慪火”,”86″,”/勝利”,”79″,”/得意”,”4″,”/驚訝”,”14″,”/心碎”,”67″,”/驚恐”,”26″,”/微笑”,”0″,”/憨笑”,”28″,”/抓狂”,”18″,”/折磨”,”35″,”/發抖”,”41″,”/握手”,”78″,”/飛吻”,”85″,”/鼓掌”,”99″,”/撇嘴”,”1″,”/敲打”,”38″,”/暈”,”34″,”/月亮”,”75″,”/流汗”,”27″,”/流淚”,”5″,”/糗大了”,”100″,”/愛心”,”66″,”/左哼哼”,”102″,”/玫瑰”,”63″,”/疑問”,”32″,”/白眼”,”22″,”/睡”,”8″,”/冷汗”,”96″,”/示愛”,”65″,”/弱”,”77″,”/跳跳”,”43″,”/色”,”2″,”/炸彈”,”55″,”/壞笑”,”101″,”/衰”,”36″,”/刀”,”56″,”/調皮”,”12″,”/摳鼻”,”98″,”/酷”,”16″,”/禮物”,”69″,”/閉嘴”,”7″,”/難過”,”15″,”/饑餓”,”24″,”/飯”,”61″,”/骷髏”,”37″,”/愛情”,”42″};
private int[] mSmileyIds = null;
private String[] mSmileyTexts = null;
public static SmileyParser getInstance() {
if (sInstance == null) {
sInstance = new SmileyParser(GameDataMgr.getInstance().getActivity());

}

return sInstance;
}
private SmileyParser(Context context) {
// TODO Auto-generated constructor stub
mContext = context;
initSmileyIds();
mPattern = buildPattern();
mSmileyTextToId = buildSmileyRes();
}

private void initSmileyIds(){
mSmileyIds = new int[mSmileyArrays.length / 2];
mSmileyTexts = new String[mSmileyArrays.length /2];
for (int i = 0; i < mSmileyArrays.length / 2; i++) {
mSmileyTexts[i] = mSmileyArrays[i*2];
mSmileyIds[i] = Integer.parseInt(mSmileyArrays[i*2 + 1]);
}
}

public int[] getSmileyIDs(){
return mSmileyIds;
}

public int getSmileyResourceId(int smileyId){
String idString = “face_” + Integer.toString(smileyId);

int id = getResId(idString, mContext, R.drawable.class);

return id;
}

public static int getResId(String variableName, Context context, Class<?> c) {

try {
Field idField = c.getDeclaredField(variableName);
return idField.getInt(idField);
} catch (Exception e) {
e.printStackTrace();
return -1;
}
}

public String[] getSmileyTexts(){
return mSmileyTexts;
}

Drawable getSmileyDrawable(int id){
Drawable drawable = null;
drawable = mContext.getResources().getDrawable(getSmileyResourceId(id));

return drawable;

}

/**
* 建立String – Id的对应关系
*/
private HashMap<String, Integer> buildSmileyRes(){

HashMap<String, Integer> smileyTextToId = new HashMap<String, Integer>(mSmileyIds.length);
for(int i = 0;i < mSmileyIds.length;++i){
smileyTextToId.put(mSmileyTexts[i], mSmileyIds[i]);
}

return smileyTextToId;
}

/**
* 建立匹配用的正则表达式
* @return
*/
private Pattern buildPattern(){
StringBuilder builder = new StringBuilder(mSmileyTexts.length * 3);
builder.append(‘(‘);
for (String  s:  mSmileyTexts) {
builder.append(Pattern.quote(s));
builder.append(‘|’);
}

builder.replace(builder.length() – 1, builder.length(), “)”);

return Pattern.compile(builder.toString());
}

/**
* 把文字转换为图片
* @param text
* @return
*/
public Spannable addSmileySpans(CharSequence text){
SpannableStringBuilder spBuilder = new SpannableStringBuilder(text);

Matcher matcher = mPattern.matcher(text);

while (matcher.find()) {
int id = mSmileyTextToId.get(matcher.group());
matcher.start(),matcher.end(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spBuilder.setSpan(new ImageSpan(mContext,getSmileyResourceId(id),ImageSpan.ALIGN_BASELINE),  matcher.start(),matcher.end(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

}

return spBuilder;
}
}

 

实现过程中遇到个小问题:往TextView中添加表情时,当文本既有表情也有文字时,显示是正常的,但是当文本中只有表情时,发现表情显示会偏上,而且上面有一部分被截断。TextView布局如下:

<TextView

android:id=”@+id/comment_item_content”

android:layout_width=”fill_parent”

android:layout_height=”wrap_content”

android:layout_marginTop=”10dp”

android:layout_marginBottom=”10dp”

android:textSize=”16sp”

android:textColor=”#333333″

/>

 

 

解决方法:这里的问题应该是TextView在判断行距的时候是根据字体来判断的,但是当文本是表情的时候这个判断有些问题,导致行距过小,所以显示表情的时候就截断了,解决方法是设置一下TextView的最小高度,同时要指定文本向下对齐。另外在创建ImagePan的时候如果指定ImageSpan.ALIGN_BOTTOM对齐方式一般是不会出现这个问题的,但是这种方式下表情显示会偏下。修改后TextView布局如下:

<TextView

android:id=”@+id/comment_item_content”

android:layout_width=”fill_parent”

android:layout_height=”wrap_content”

android:layout_marginTop=”10dp”

android:layout_marginBottom=”10dp”

android:textSize=”16sp”

android:textColor=”#333333″

android:minHeight=”25dp”

android:gravity=”bottom”

/>