1,下载ProtocolBuffer包,并按照包中根目录下README.txt安装。
http://code.google.com/intl/zh-CN/apis/protocolbuffers/
当前最新版本2.4.1
最后make install后,会生成编译器protoc,并拷贝到/usr/local/bin目录下。
2,下载Objective-C compiler for ProtocolBuffer。
目前有两种类型的实现。
一个针对ProtocolBuffer2.2做修改,使最后生成的.proto文件编译器(protoc)支持Objective-C类型的文件输出。
它在这里:http://code.google.com/p/metasyntactic/wiki/ProtocolBuffers
另一个针对ProtocolBuffer2.3推出的plugin模式编写插件,以插件方式支持Objective-C类型的文件输出。
它在这里:https://github.com/booyah/protobuf-objc
我选用第二种方式,这也是Google推荐的方式。
git clone https://github.com/booyah/protobuf-objc.git
默认会在当前运行目录下创建protobuf-objc目录。进入该目录,并执行:
./autogen.sh
./configure
make
make install
最终生成的插件名字为protoc-gen-objc,会被安装到/usr/local/bin/目录下。
3,测试.proto文件编译。
随便写一个test.proto文件,并编译该文件。命令是:
protoc –objc_out=/Output/Directory/ test.proto
protoc会自动在/usr/local/bin/目录下寻找名为”protoc-gen-objc”的插件,并使用该插件编译.proto文件,最终生成两个文件:
test.pb.h
test.pb.m
这个步骤通过后,说明ProtocoBuffer Compiler for Objective-C可以正常工作了。
4,在Xcode4.3.1中使用ProtocolBuffer
将步骤2中protobuf-obj/src/runtime/Classes目录导入到Xcode项目中,导入时,选中”Copy items into destination group‘s folder(if needed)“。
导入位置选择项目根目录。导入完毕后,项目根目录下将会出现Classes目录。将该目录改名为ProtocolBuffers(注意最后的s):
mv Classes ProtocolBuffers
修改项目属性中”Build Setting——>Header Search Pathes”,将项目根目录“.”添加到头文件搜索路径中去。
这样ProtocolBuffer for Objective-C的工作环境就配置好了。
5,使用
将步骤3中编译输出的test.pb.h和test.pb.m添加到项目中,就可以直接使用了。
写一个servlet实现GPS坐标偏移接口功能
这两天写了一个servlet,用于实现GPS坐标偏移接口功能。大概就是,我需要首先接收一个经纬度串数组,然后用json解析,给URL服务发送请求,服务器返回json格式的数组.
0、需要引入json-simple-1.1的类库。
1、GPS坐标偏移接口文档见附件
2、具体servlet代码:
package com.tm.gpsController;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class GPSConventCoordinateServlet extends HttpServlet {
private static final long serialVersionUID = 3018725984829044717L;
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 我申请的key
String a_k = "XXXXXX";
String coors = req.getParameter("lonLatStr");
JSONParser parser = new JSONParser();
Object obj = "";
try {
obj = parser.parse(coors);
} catch (ParseException e) {
e.printStackTrace();
}
String lonLatStr = "";
JSONArray array = (JSONArray) obj;
for (Object j : array) {
//
lonLatStr = lonLatStr + ((JSONObject) j).get("lon") + ","
+ ((JSONObject) j).get("lat") + ";";
}
lonLatStr = lonLatStr.substring(0, lonLatStr.length() - 1);
String postParam = "config=RGC&flag=true&resType=json&cr=0&coors="
+ lonLatStr + "&a_k=" + a_k;
System.out.println(postParam);
// 服务地址
String urlString = "XXXXXX";
URL url = new URL(/blog_article/urlString/index.html);
URLConnection urlc = url.openConnection();
HttpURLConnection httpConnection = (HttpURLConnection) urlc;
httpConnection.setRequestMethod("POST");
httpConnection.setDoInput(true);
httpConnection.setDoOutput(true);
httpConnection.connect();
OutputStreamWriter osw = new OutputStreamWriter(
new BufferedOutputStream(httpConnection.getOutputStream()));
osw.write(postParam);
osw.flush();
System.out.println();
osw.close();
BufferedReader br = new BufferedReader(new InputStreamReader(
httpConnection.getInputStream()));
String line;
StringBuffer sbuffB = new StringBuffer();
while ((line = br.readLine()) != null) {
sbuffB.append(line + "\n");
System.out.println(line);
}
br.close();
httpConnection.disconnect();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
3、web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>GPSConventCoordinateServlet</servlet-name>
<servlet-class>com.tm.gpsController.GPSConventCoordinateServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GPSConventCoordinateServlet</servlet-name>
<url-pattern>/GPSConventCoordinateServlet</url-pattern>
</servlet-mapping>
</web-app>
4、启动tomcat,部署一下,运行。
5、在浏览器中输入
http://localhost:8080/gpsCoordinateConvent/GPSConventCoordinateServlet?lonLatStr=[{"lon":133.34,"lat":35.33},{"lon":134.33,"lat":34.33]进行测试。
6、在控制台输出返回的信息{"message":"ok","list":[{"gridcode":"873482645301","y":"582.5422219509549","x":"582.5422219509549"},{"gridcode":"873482645301","y":"582.5422219509549","x":"582.5422219509549"}]} 就对了
7、注意 在浏览器中输入的参数lonLatStr=[{"lon":133.34,"lat":35.33},{"lon":134.33,"lat":34.33] 参数格式有时候输入的特殊,服务器端就会返回一个默认的返回的结果。"[{"gridcode":"873482645301","y":"582.5422219509549","x":"582.5422219509549"},这时候,其实程序是没有问题的,只需要改一下参数,就可以了。
据说,腾讯的产品的三字名言是:抄、糙、超。即,先抄袭、在模仿、最终实现超越。互联网软件天下一大抄,彼此抄袭是常事,关键使我们如何超越他人,实现自我。下面我们采用最新的QQ阅读器反编译代码,并恢复源代码,学习QQ阅读器的架构和具体实现。
1. 首先我们需要2个工具来反编译QQ阅读器Android端的源代码:apktool和dex2jar
2. 最新QQ阅读器安装文件(qqreader_2.1.1.0150_android.apk)
3. 反编译文件,导入eclipse中
apktool.bat d qqreader.apk qqreader
dex2jar.bat classes.dex
使用jd-gui.exe代开src.zip文件,并保存到本地所有src源文件,至此QQReader的源代码和资源文件全部反编译完成,新建android2.1工程,并导入工程后,发现无数的错误,没关系,翻遍编译后是源代码那就真奇怪了。源代码见附件,注意工程是UTF-8格式的。
4. 首先启动的是ReaderApplication,关键代码
@Override public void onCreate() { super.onCreate(); new d(this.getApplicationContext()); new c(); }
对D和C进行初始化,作用不详,表面上看无作用
5. 然后启动的Activity是SplashActivity,即LOGO页面,继承了阅读器的基类,TA是整个安卓应用的入口类ReaderBaseActivity.java。这个类提供了可重复使用的一些代码,如
1. 是否要下载更新软件版本, msg.what = 310,提示:网络错误、更新失败、更新成功、已是最新版本 msg.what=104,提示:是否退出阅读器 2. 设置默认对话框的样式 3. 获取底层的一些常用的对象 4. 重载父类的onPause和onDestory方法,记录日志打点信息 5. onCreate:获取屏幕的宽高 屏幕高大于1280,设置字体的初始大小18、15 960:8、15 800:8、15 320:默认 否则:-4(减去) 6. onResume: 这个是QQ阅读器的亮点,每个activity重新恢复展示时,都会调用这个函数,其中QQ设置了全局变量,如果全局变量是否退出应用程序,那么,调用finish()函数,一次循环递归,知道所有的acitivity都执行了finish()函数,应用退出。
ReaderBaseActivity的基本作用讲完了,这个时候才是真正启动SplashActivity的。
1. OnCreate函数
1. 设置全局静态变量finish=false;初始化系统状态为非终止状态(ay.a(false);)
2. 设置noTitle展示(requestWindowFeature(1);)
3. 设置layout为splash.xml。这个布局就一张ImageView(setContentView(2130903126);)
4. 发送异步消息
SplashActivity.a(this.a).sendEmptyMessage(1);是否继续下载更新文件 SplashActivity.a(this.a).sendEmptyMessage(3);距离安装时间超过7天后,每次启动检查是否有新版本,有的话,就要提示 SplashActivity.a(this.a).sendEmptyMessage(2);检查是否是第一次运行,根据这个展示操作指南,并拷贝默认的图书到书架。 SplashActivity.a(this.a).sendEmptyMessage(4);下载一些东西,代码反编译失败 SplashActivity.a(this.a).sendEmptyMessageDelayed(0, 800L);延迟0.8s启动书架
2. onKeyDown函数:禁用返回键
至此,QQ阅读器从点击快捷方式,到logo的展示已经完成,接下来就是进入书架模块。