2013年1月27日 星期日

无Java开发Android应用(NativeActivity)

最新的 Android 2.3 无需 Java 就可以开发应用,详情请看 这里。
这里是官方给的例子程序 ,来自:http://developer.android.com/reference/android/app/NativeActivity.html

代码片段(2)

[代码] AndroidManifest.xml

01<manifest xmlns:android="http://schemas.android.com/apk/res/android"
02        package="com.example.native_activity"
03        android:versionCode="1"
04        android:versionName="1.0">
05  
06    <!-- This is the platform API where NativeActivity was introduced. -->
07    <uses-sdk android:minSdkVersion="8" />
08  
09    <!-- This .apk has no Java code itself, so set hasCode to false. -->
10    <application android:label="@string/app_name" android:hasCode="false">
11  
12        <!-- Our activity is the built-in NativeActivity framework class.
13             This will take care of integrating with our NDK code. -->
14        <activity android:name="android.app.NativeActivity"
15                android:label="@string/app_name"
16                android:configChanges="orientation|keyboardHidden">
17            <!-- Tell NativeActivity the name of or .so -->
18            <meta-data android:name="android.app.lib_name"
19                    android:value="native-activity" />
20            <intent-filter>
21                <action android:name="android.intent.action.MAIN" />
22                <category android:name="android.intent.category.LAUNCHER" />
23            </intent-filter>
24        </activity>
25    </application>
26  
27</manifest>

[代码] Demo.c

001#include <jni.h>
002#include <errno.h>
003  
004#include <EGL/egl.h>
005#include <GLES/gl.h>
006  
007#include <android/sensor.h>
008#include <android/log.h>
009#include <android_native_app_glue.h>
010  
011#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
012#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
013  
014/**
015 * Our saved state data.
016 */
017struct saved_state {
018    float angle;
019    int32_t x;
020    int32_t y;
021};
022  
023/**
024 * Shared state for our app.
025 */
026struct engine {
027    struct android_app* app;
028  
029    ASensorManager* sensorManager;
030    const ASensor* accelerometerSensor;
031    ASensorEventQueue* sensorEventQueue;
032  
033    int animating;
034    EGLDisplay display;
035    EGLSurface surface;
036    EGLContext context;
037    int32_t width;
038    int32_t height;
039    struct saved_state state;
040};
041  
042/**
043 * Initialize an EGL context for the current display.
044 */
045static int engine_init_display(struct engine* engine) {
046    // initialize OpenGL ES and EGL
047  
048    /*
049     * Here specify the attributes of the desired configuration.
050     * Below, we select an EGLConfig with at least 8 bits per color
051     * component compatible with on-screen windows
052     */
053    const EGLint attribs[] = {
054            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
055            EGL_BLUE_SIZE, 8,
056            EGL_GREEN_SIZE, 8,
057            EGL_RED_SIZE, 8,
058            EGL_NONE
059    };
060    EGLint w, h, dummy, format;
061    EGLint numConfigs;
062    EGLConfig config;
063    EGLSurface surface;
064    EGLContext context;
065  
066    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
067  
068    eglInitialize(display, 0, 0);
069  
070    /* Here, the application chooses the configuration it desires. In this
071     * sample, we have a very simplified selection process, where we pick
072     * the first EGLConfig that matches our criteria */
073    eglChooseConfig(display, attribs, &config, 1, &numConfigs);
074  
075    /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
076     * guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
077     * As soon as we picked a EGLConfig, we can safely reconfigure the
078     * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
079    eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
080  
081    ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);
082  
083    surface = eglCreateWindowSurface(display, config, engine->app->window, NULL);
084    context = eglCreateContext(display, config, NULL, NULL);
085  
086    if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
087        LOGW("Unable to eglMakeCurrent");
088        return -1;
089    }
090  
091    eglQuerySurface(display, surface, EGL_WIDTH, &w);
092    eglQuerySurface(display, surface, EGL_HEIGHT, &h);
093  
094    engine->display = display;
095    engine->context = context;
096    engine->surface = surface;
097    engine->width = w;
098    engine->height = h;
099    engine->state.angle = 0;
100  
101    // Initialize GL state.
102    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
103    glEnable(GL_CULL_FACE);
104    glShadeModel(GL_SMOOTH);
105    glDisable(GL_DEPTH_TEST);
106  
107    return 0;
108}
109  
110/**
111 * Just the current frame in the display.
112 */
113static void engine_draw_frame(struct engine* engine) {
114    if (engine->display == NULL) {
115        // No display.
116        return;
117    }
118  
119    // Just fill the screen with a color.
120    glClearColor(((float)engine->state.x)/engine->width, engine->state.angle,
121            ((float)engine->state.y)/engine->height, 1);
122    glClear(GL_COLOR_BUFFER_BIT);
123  
124    eglSwapBuffers(engine->display, engine->surface);
125}
126  
127/**
128 * Tear down the EGL context currently associated with the display.
129 */
130static void engine_term_display(struct engine* engine) {
131    if (engine->display != EGL_NO_DISPLAY) {
132        eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
133        if (engine->context != EGL_NO_CONTEXT) {
134            eglDestroyContext(engine->display, engine->context);
135        }
136        if (engine->surface != EGL_NO_SURFACE) {
137            eglDestroySurface(engine->display, engine->surface);
138        }
139        eglTerminate(engine->display);
140    }
141    engine->animating = 0;
142    engine->display = EGL_NO_DISPLAY;
143    engine->context = EGL_NO_CONTEXT;
144    engine->surface = EGL_NO_SURFACE;
145}
146  
147/**
148 * Process the next input event.
149 */
150static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
151    struct engine* engine = (struct engine*)app->userData;
152    if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
153        engine->animating = 1;
154        engine->state.x = AMotionEvent_getX(event, 0);
155        engine->state.y = AMotionEvent_getY(event, 0);
156        return 1;
157    }
158    return 0;
159}
160  
161/**
162 * Process the next main command.
163 */
164static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
165    struct engine* engine = (struct engine*)app->userData;
166    switch (cmd) {
167        case APP_CMD_SAVE_STATE:
168            // The system has asked us to save our current state.  Do so.
169            engine->app->savedState = malloc(sizeof(struct saved_state));
170            *((struct saved_state*)engine->app->savedState) = engine->state;
171            engine->app->savedStateSize = sizeof(struct saved_state);
172            break;
173        case APP_CMD_INIT_WINDOW:
174            // The window is being shown, get it ready.
175            if (engine->app->window != NULL) {
176                engine_init_display(engine);
177                engine_draw_frame(engine);
178            }
179            break;
180        case APP_CMD_TERM_WINDOW:
181            // The window is being hidden or closed, clean it up.
182            engine_term_display(engine);
183            break;
184        case APP_CMD_GAINED_FOCUS:
185            // When our app gains focus, we start monitoring the accelerometer.
186            if (engine->accelerometerSensor != NULL) {
187                ASensorEventQueue_enableSensor(engine->sensorEventQueue,
188                        engine->accelerometerSensor);
189                // We'd like to get 60 events per second (in us).
190                ASensorEventQueue_setEventRate(engine->sensorEventQueue,
191                        engine->accelerometerSensor, (1000L/60)*1000);
192            }
193            break;
194        case APP_CMD_LOST_FOCUS:
195            // When our app loses focus, we stop monitoring the accelerometer.
196            // This is to avoid consuming battery while not being used.
197            if (engine->accelerometerSensor != NULL) {
198                ASensorEventQueue_disableSensor(engine->sensorEventQueue,
199                        engine->accelerometerSensor);
200            }
201            // Also stop animating.
202            engine->animating = 0;
203            engine_draw_frame(engine);
204            break;
205    }
206}
207  
208/**
209 * This is the main entry point of a native application that is using
210 * android_native_app_glue.  It runs in its own thread, with its own
211 * event loop for receiving input events and doing other things.
212 */
213void android_main(struct android_app* state) {
214    struct engine engine;
215  
216    // Make sure glue isn't stripped.
217    app_dummy();
218  
219    memset(&engine, 0, sizeof(engine));
220    state->userData = &engine;
221    state->onAppCmd = engine_handle_cmd;
222    state->onInputEvent = engine_handle_input;
223    engine.app = state;
224  
225    // Prepare to monitor accelerometer
226    engine.sensorManager = ASensorManager_getInstance();
227    engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
228            ASENSOR_TYPE_ACCELEROMETER);
229    engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager,
230            state->looper, LOOPER_ID_USER, NULL, NULL);
231  
232    if (state->savedState != NULL) {
233        // We are starting with a previous saved state; restore from it.
234        engine.state = *(struct saved_state*)state->savedState;
235    }
236  
237    // loop waiting for stuff to do.
238  
239    while (1) {
240        // Read all pending events.
241        int ident;
242        int events;
243        struct android_poll_source* source;
244  
245        // If not animating, we will block forever waiting for events.
246        // If animating, we loop until all events are read, then continue
247        // to draw the next frame of animation.
248        while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events,
249                (void**)&source)) >= 0) {
250  
251            // Process this event.
252            if (source != NULL) {
253                source->process(state, source);
254            }
255  
256            // If a sensor has data, process it now.
257            if (ident == LOOPER_ID_USER) {
258                if (engine.accelerometerSensor != NULL) {
259                    ASensorEvent event;
260                    while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
261                            &event, 1) > 0) {
262                        LOGI("accelerometer: x=%f y=%f z=%f",
263                                event.acceleration.x, event.acceleration.y,
264                                event.acceleration.z);
265                    }
266                }
267            }
268  
269            // Check if we are exiting.
270            if (state->destroyRequested != 0) {
271                engine_term_display(&engine);
272                return;
273            }
274        }
275  
276        if (engine.animating) {
277            // Done with events; draw next animation frame.
278            engine.state.angle += .01f;
279            if (engine.state.angle > 1) {
280                engine.state.angle = 0;
281            }
282  
283            // Drawing is throttled to the screen update rate, so there
284            // is no need to do timing here.
285            engine_draw_frame(&engine);
286        }
287    }
288}


資料來源    http://www.oschina.net/code/snippet_12_2904

Android混淆、反编译以及反破解的简单回顾

一、Android混淆
1)概述
         新建Android工程,根目录下会有个proguard.cfg。简单的混淆,你只需要在project.properties内加入一行“proguard.config=proguard.cfg”即可。
         注意:在签名发布apk时才会混淆,直接Run As在bin目录下的apk是不被混淆的。签名发布:右键工程->Android Tools->Export Signed Application Package…
         如何生成签名,可以参考《Android 数字签名学习笔记》。
 
2)外部jar
         未混淆过的,只加个类库声明就好。例如,用到“SDK目录\ extras\android\support\v4\ android-support-v4.jar”时,可以在-keep前加如下内容即可:
  1. -dontwarn android.support.** 
  2. -libraryjars lib/android-support-v4.jar 
         第一行,表示去除警告,第二行是声明jar(jar包拷到工程内了,所以是相对目录==)。
         这样混淆后,引用的jar包也会一起被混淆。
 
         如果用的第三方jar包是被混淆过的,或你不想混淆,则用-keep去除即可。例如,之前android-support-v4.jar,如果不需要混淆它的话,可以增加这么一句:
  1. -keep class android.support.v4.** { 
  2.         *; 
  3. } 
         此时的话,jar包就不会被混淆了^^。
 
         更详细的使用方法,请参看小节3。
 
1. 在手册的样例中,有两篇即是讲述Android的,如下:
         Manual->Examples->A simple Android activity&A complete Android application
2. 用法的内容,则在:Manual->Usage。用于学习或查看各命令都是做什么的用。
 
中文相关的话,可以参考下述网址,呼呼~
 
4)可能问题
4.1)新建工程下没有proguard.cfg
         你的环境太老了吧==。
         ProGuard是2.2才加的?记得我起初低于2.2的混淆时,要从2.2工程下把proguard.cfg拷过去。当时建2.1的目录下是没proguard.cfg的。
         不过现在建立个1.5都是有这个文件的。
 
二、Android反编译
1)概述
         apktool + dex2jar + jd-gui。超链接是主页,不了解的可以看看介绍,再转至Downloads。
 
         具体做什么用的或如何操作,参看小节2。
 
         当然,和之前《批处理安装&卸载apk》一样,小子懒人一个T^T。又是批处理(没sh的……):
easyTool.bat
  1. @echo off 
  2. title APK反编译[by Join] 
  3.  
  4. rem apktool目录 
  5. set p_at="E:\zhao\environment\decompile\apktool" 
  6. rem dex2jar目录 
  7. set p_dj="E:\zhao\environment\decompile\dex2jar-0.0.9.8" 
  8. rem dex2jar后缀 
  9. set suffix=_dex2jar.jar 
  10.  
  11. if "%~1"=="" echo 请将apk直接拖放至bat文件!&goto :over 
  12.  
  13. rem 增加apktool路径 
  14. set path=%p_at%;%p_dj%;%path% 
  15.  
  16. setlocal enabledelayedexpansion 
  17. if /i "%~x1"==".apk" ( 
  18.   echo apktool处理"%~nx1"中... 
  19.   apktool d "%~1" "%~dpn1" 
  20.   echo dex2jar处理"%~nx1"中... 
  21.   dex2jar.bat "%~1" 
  22.   rem dex2jar执行后直接结束了== 
  23.   echo 移动文件"%~n1!suffix!"中... 
  24. ) else ( 
  25.   echo 文件类型错误:不支持%~x1! 
  26. ) 
  27.  
  28. :over 
  29. echo. 
  30. @pause>nul 
         保存成bat,修改下apktool目录&dex2jar目录,将apk拖上去即可。会有一个“同名”文件夹和一个“同名_dex2jar.jar”的文件。文件夹是apktool生成的资源,jar则是dex2jar反编译出的代码。然后用jd-gui打开jar即可。
         注意:dex2jar需要用最新的,可以直接用于apk。代码增加了zip解压,不再需要手动了,不清楚哪个版本开始的==。才发现的,bat也刚升级了下。
 
2)更多
         看这篇文章就可以了:android反编译小结。
 
三、Android反破解
         不废话,参见“看雪学院->Android软件安全->APK反破解技术小结”。
         那位版主现总结了四篇文章,如下:
 
         还有一些回复和摘录,如下:
 
1)可以介绍一下openssl工具,挺好用的。
 
2) 以下为一段整合的回复:
-> 呵呵~!代码混淆能避免被别人破解吗?
-> 不能,只是会增加别人破解的难度。如果要防别人破解的话,最好的方法是使用NDK,用C、C++写的代码,用NDK编成so库,用JNI进行调用!
-> SO库文件包含符号, 调试也比java代码方便, 所以某种意义上说逆向so里面的native code比逆向java还容易。
-> Open Source 成就了 GNU Tool-chain. ELF里面符号表是“一等公民”. 所以默认选项生成的目标文件里面带符号,虽然可以通过选项分离符号,但是很多时候都会忽略了这一点。
不过我相信Open Source模式才是未来软件工程的王道。
 
3)可以多关注dalvik是怎么实现java对JNI调用的。其中会涉及到怎么定位一个native func,有文章可做。
 
4)Dalvik虚拟机类加载机制的SDK类
         A class loader that loads classes from .jar and .apk files containing a classes.dex entry.
         Provides a simple ClassLoader implementation that operates on a list of files and directories in the local file system, but does not attempt to load classes from the network.
 
四、后记
         我用Proguard觉得最大的好处不在于混淆,而在于压缩了代码,apk整整能瘦一圈呢^^
 
五、补充——反编译odex文件
         没关注过ROM,在反编译4.0系统framework.jar定制SDK时,才发现odex这个东西==。
 
         这里也就直接以这举例了^^
 
1. 下载baksmali-1.3.2.jar & smali-1.3.2.jar
2. 模拟器导出整个/system/framework/
         baksmali 反编译是自动找5个核心的BOOTCLASSPATH,当然某些可能会涉及其他的CLASSPATH需要指定-c再添加。
         总之全部弄出来得了,ROM的话也一样吧?不同公司应该会涉及自己的一些包,就这边加吧?
3. 把两个jar放进导出的framework目录
4. 进入framework目录
5. 以下命令进行反编译啦~
java -Xmx512m -jar baksmali-1.3.2.jar -x framework.odex -o out(反编译进out目录)
java -Xmx512M -jar smali-1.3.2.jar -o classes.dex out(重新生成classes.dex)
         第一条命令的话,现版本-a默认为14。出UNEXPECTED TOP-LEVEL EXCEPTION,可能是这出错,记得指定正确。-c,默认会找5个核心CLASSPATH,其他自己指定了。
6. 继而的话,可以用来整成一个apk,或继续dex2jar反编译咯~
 
         参考网址:
                   apk生成odex & 合并odex和少dex的apk为完整apk。
                   当然用这两个jar时,可以先-h看参数说明也差不多。
 

分享:Android中利用机器码注册机制防止破解 .

最近做一个Android应用时遇到这个问题,客户要求功能必须注册才能使用,而程序本身又不是联网在线使用的,这就要在程序中加入机器码注册码机制了。

众所皆知Android应用是基于Java开发,如不做处理的话,直接反编译APK就能看到源码算法,要破解就没什么难度了。
关于Android防破解,网上有价值的内容较少。我收集了一些零碎的资料,总结起来大概有以下几种防破解的思路方式:
1.代码混淆。2.3的Android SDK已经支持直接混淆生成APK。混淆能加大反编译破解的难度,但光混淆不能解决问题,对于有经验的人来说,在混淆代码中找到注册检查代码进行强行破解也不是难事。
2.签名比对。APK中可使用签名进行处理,不过APK的签名不能防止反编译,只是反编译后不能再使用同一个签名而已。虽然可在代码中进行比对签名,但比对代码本身也可能被修改掉。因此签名的作用不大。
3.联网注册。程序启动后自动连接到服务器进行注册验证,并把一部分核心功能放到服务端。这种方式是最安全,不过对于单机程序就不合适了,总不能在一个记事本程序中也要求用户登录服务器吧。
4.dex或class动态加载。这种方式理论不错,把一小部分核心算法做成dex或class文件,加密为资源文件,注册成功后才解密并加载到内存中。但这个方式实现起来难度很高,我似乎没有在网上找到实现的文章,实现后维护代码成本也高。另外,如果将程序完全反编译后进行调试,也仍然能下断点把解密的dex或class文件给导出来。
5.使用NDK(或JNI)本地C/C++动态库。对于单机应用程序来说,这个是比较好的解决办法了。NDK编译的原生C/C++程序调试破解的难度比较高,代码维护也方便。
要加大破解难度,还有其它一些要注意的:可对关键内容或算法进行加密;把检测算法分解成零碎片段多处调用;另外注册相关的敏感字符串(如“注册失败”之类的消息)一律不以明文出现,等等。
我最终选择的注册机制方案是:代码混淆+NDK库+内容加密。简单说明如下:
1.对所有JAVA代码进行混淆。我之前写的程序是Android2.2的,不支持直接混淆;后来我下载了最新的SDK,将程序的SDK版本号target设置为13,在default.properties中增加proguard.cfg,然后在工程中右键Tools导出签名的APK完成混淆打包过程。
2.用NDK C语言实现机器码的生成、注册码的检测和内容的解密。在JAVA界面中只做机器码的显示、注册码的输入和调用加解密接口,而核心的机器码注册码加解密全在C程序中完成。机器码要跟硬件ID之类的结合,稍为要注意下的是不能直接用WIFI的MAC地址,因为WIFI的MAC地址容易被修改;最好是用CPU序列号,如果没有的话可考虑用设备ID IMEI或USB的MAC码,但最好不要在JAVA代码中获取,而是要在JNI C代码里获取,以免被反编译后篡改。生成过程这里就不细述了,以后有时间再写一下。
3.对部分资源文件进行加解密处理。程序运行中要使用文件系统中的资源文件才能运行,因此我把这些文件事先在PC上加密,并把解密密钥放在注册码中。根据机器码生成注册码,生成器注册码时将解密密钥加入。由于解密的密钥包含在注册码中,破解者即使将注册检测绕过,也无法解密文件运行;只能获得一个注册码才能执行解密。由于注册码检测和解密过程在NDK程序中完成,因此即使有一个注册码,也难以获得解密的密钥和算法。
当然了,防止破解是相对的,没有完全绝对不能破解的程序,只是让破解的难度成本高到还不如直接注册就行了。反过来说,如果你的程序本身没什么价值或没多少人会用,那基本上防破解也没什么必要。


資料來源
http://blog.csdn.net/huzgd/article/details/6684094

2013年1月14日 星期一

gallery 显示文字

有时候想 向左向右设置文字的变化 不妨试试gallery
  • <LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"  
  • android:id="@+id/widget44"  
  • android:layout_width="fill_parent"  
  • android:layout_height="fill_parent"  
  • android:orientation="vertical"  
  • android:gravity="center_horizontal">   
  •     <TextView   
  •         android:id="@+id/txt1_gvi"  
  •         android:layout_width="wrap_content"  
  •         android:layout_height="wrap_content"  
  •         android:textColor="#051b4d"  
  •         android:gravity="center_horizontal"  
  •         android:textColorHighlight="#656565"  
  •         android:textSize="10sp">   
  •     </TextView>   
  • </LinearLayout>  


    1. public Activity activity;   
    2.     private static LayoutInflater inflater=null;   
  •     private String [] stringid=new String[]{"Index-Nifty","Positional calls","Intraday calls","InvestmentIdea","Optional calls","BTST-STBT calls"};        
  •   
  •     public TabGallary(Activity a) {        
  •         activity = a;   
  •         inflater =  (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);   
  •     }   
  •   
  •     public int getCount(){   
  •         return stringid.length;   
  •     }      
  •   
  •     public Object getItem(int position) {   
  •         return position;   
  •     }   
  •   
  •     public long getItemId(int position) {   
  •         return position;   
  •     }   
  •   
  •     public View getView(int position, View convertView, ViewGroup parent)      
  •     {              
  •       View v;                        
  •       if (convertView == null)    
  •       {     
  •            LayoutInflater li = getLayoutInflater();   
  •            v = li.inflate(R.layout.demo, null);   
  •            TextView tv1 = (TextView)v.findViewById(R.id.txt1_gvi);    
  •            tv1.setText(stringid[position]);   
  •            v.setOnClickListener(new OnClickListener()    
  •            {                       
  •                     @Override  
  •                     public void onClick(View v)    
  •                     {   
  •                   // Call intent or perform ur activity;                   
  •                     }   
  •            });         
  •       }   
  •       else    
  •       {   
  •        v= convertView;   
  •       }        
  •   
  •       return v;   
  •    }  
  • 2013年1月8日 星期二

    星期英文转中文解决方法

    Java code
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.TimeZone;
    import java.util.Date;
    
    public class WeekShow {
    
        public static void main(String[] args) {
            DateFormat df=new SimpleDateFormat("EE");
            df.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
            Date d=new Date();//这里改成你从数据库获得的时间构造一个Date
            String s=df.format(d);
            System.out.println("output:"+s);
        }
    }
    

    JAVA将英文格式的日期字符串转换为时间

    JAVA将英文格式的日期字符串转换为时间

    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Locale;
    public class test {
     public static void main(String[] args) throws ParseException {
      String temp = "Thu,1Dec201111:16:25GMT";
      SimpleDateFormat sdf = new SimpleDateFormat("EEE,dMMMyyyyHH:mm:ssz",Locale.US);  Date d=sdf.parse(temp);
      long longTime=d.getTime()-8*60*60*1000;
      Date d2=new Date(longTime);
      System.out.println(d2);
     
     }
    }

    主要是设置Locale,可以点一下看看都有哪些值。
    G  Era 标志符  Text  AD 
    y  年  Year  1996; 96 
    M  年中的月份  Month  July; Jul; 07 
    w  年中的周数  Number  27 
    W  月份中的周数  Number  2 
    D  年中的天数  Number  189 
    d  月份中的天数  Number  10 
    F  月份中的星期  Number  2 
    E  星期中的天数  Text  Tuesday; Tue 
    a  Am/pm 标记  Text  PM 
    H  一天中的小时数(0-23)  Number  0 
    k  一天中的小时数(1-24)  Number  24 
    K  am/pm 中的小时数(0-11)  Number  0 
    h  am/pm 中的小时数(1-12)  Number  12 
    m  小时中的分钟数  Number  30 
    s  分钟中的秒数  Number  55 
    S  毫秒数  Number  978 
    z  时区  General time zone  Pacific Standard Time; PST; GMT-08:00 
    Z  时区  RFC 822 time zone  -0800