仓蓝

日记本

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  23 Posts :: 0 Stories :: 1 Comments :: 0 Trackbacks

#

随着手机的功能越来越丰富,支持横竖屏切换的手机越来越多,在手机软件开发中也必须要处理这个功能了。下面对于使用J2ME技术进行编程时对于横竖屏(转屏)切换时的相关知识进行一下小结。

1、如何判断横竖屏切换

横竖屏切换由手机系统自动完成的,在J2ME中只能检测到这种变换,判断横竖屏切换的方法有2种:

A)线程中每次检测法(轮询方式)

这种方式是在程序的线程中每隔一定的时间间隔,就获得一次屏幕的宽度和高度,然后判断宽度和高度是否变化,如果宽度和高度和已有的宽度和高度相比发生了变化,至于是变化成横屏还是竖屏则只需要比较宽高就可以实现。在判断到横竖屏切换时,执行逻辑代码即可。

使用这种方式由于每次线程循环都需要检测,所以执行效率不高,但是由于一些转屏手机不支持sizeChanged的方法回调,所以使用这种方式的通用性是最高的,是经常被使用的方法。

B)sizeChanged法(中断方式)

这种方式是指如果转屏手机对于MIDP支持比较规范,则当横竖屏切换时会自动调用Canvas类中的sizeChanged方法,这样就需要在Canvas的子类中覆盖该方法即可,在该方法内部书写横竖屏切换的逻辑处理代码即可。

使用这种方式由于是系统自动调用,所以执行效率很好,但是由于部分手机实现的不规范,所以通用性没有第一种方式高。

说明:高级用户界面自动切换,不需要书写处理的代码。

2、如何处理横竖屏切换

在检测到横竖屏切换以后,就需要对于横竖屏切换进行处理了,处理的方式一般有也有两种:

A)简单提示法

这种处理方式时指只实现一种屏幕模式下的逻辑,而在另外一种屏幕方式下显示提示。例如只实现竖屏模式的界面,在横屏模式下,只出现提示:“请在竖屏模式下使用本程序”。

使用这种方式程序实现比较简单,只需要实现一套界面即可,适合于比较简单的程序。

B)实现两套UI法

这种处理方式时指在一个程序中实现两套界面:一套横屏一套竖屏。可以在程序中设置一个screenType的参数,在每个节目的绘制上海电磁阀方法中根据该参数判断是横屏还是竖屏,然后执行不同的绘制代码即可。

使用这种方式程序实现比较友好,但是程序开发和测试的工作量都要稍微大一点,而且横竖屏切换时数据的变换也比较麻烦。

3、其它说明

在实现横竖屏切换时,有些知识会帮助你实现一些很实用的功能:

在Nokia手机上禁止横竖屏切换:

在S60 5th 及以上版本中,可以通过在jad或manifest文件中通过指定如下属性来指定程序运行时的屏幕类型:

竖屏:Nokia-MIDlet-App-Orientation:portrait

横屏:Nokia-MIDlet-App-Orientation:landscape

不足之处希望大家积极指正、交流和完善!


posted @ 2012-02-07 10:53 cangshi 阅读(304) | 评论 (0)编辑 收藏

  在网上广为流传的一份BlackBerry应用程序开发者指南里边详细介绍如何用BlackBerry API开发BlackBerry application的各方面内容。

  但是我们一般都是用Java ME开发,开发出来的程序是jar格式,可以运行在大部分型号的手机上。可是BlackBerry是不支持jar的,它支持的是cod格式。所以如果你想你开发的Java ME程序运行在BlackBerry上,就必须先把它转为cod格式。

  要把一般Java ME程序转为cod可以在程序开发编译过程序中转,也可以对打包好的jar转。

  ◆对已经打包好的jar文件转为BlackBerrycod格式:进入jar文件所在目录,在cmd(命令行)中进入相应目录,输入下边命令就可以了:引用rapc import="C:\Program Files\Research In Motion\BlackBerry JDE 4.2.1\lib\net_rim_api.jar" codename=TestBB jad=TestBB.jad TestBB.jar

  (注:这里rapc 是 C:\Program Files\Research In Motion\BlackBerry JDE 4.2.1\bin\ 目录里的 rapc.exe, 如果环境变量没有设置,这里就要用绝对路径:C:\Program Files\Research In Motion\BlackBerry JDE 4.2.1\bin\rapc, 当然你可以把它写成一个.bat文件来执行。而网上你可以搜索到一个名为Java2Cod.exe的小程序可以直接转换。)

  ◆在JDE中编译程序:无论你是用BlackBerry API或者Java ME/midp API来开发Java ME程序,都可以在JDE上编译。最终他会自动打包成cod文件。

  ◆在其IDE中编译打包:因为我是用NetBeans来开发的,所以本人只能提供NetBeans开发BlackBerry程序的见解。而本人是在 NetBeans中用Java ME polish来整合开发的。下边介绍Java ME polish中开发BlackBerry程序

  (可以参考http://www.j2mepolish.org/docs/platform-blackberry.html

  一、在Java ME polish安装目录里找到platforms.xml,在里边的BlackBerry部分中,加上<capability name="build.Finalizer" value="jar2cod" />(我用的是Preview 2.0版本,里边这一句是注释掉,所以要把它activate,也可以在devices.xml中在你想用的emulator 属性里加上这一句。如果没有这一句编译时就不会自动把jar转换为cod文件的.)

  polish里支持的版本最新系4.2.0,如果你安装BlackBerry版本最新的如4.2.1/4.3.0,哪么你要把${BlackBerry目录}/lib/net_rim_API.jar copy到${Java MEpolish}/import里,在platforms.xml的BlackBerry中修改<capability name="build.BootClassPath" value="net_rim_API.jar" />

  二、在工程的build.xml中添加blackberry.home属性(你安装的BlackBerry JDE目录)

  Java代码

  1. <property        name="blackberry.home" 
  2.  location="C:/Program Files/Research In Motion/BlackBerry JDE 4.2.1" /> 

  三、如果你编译后打包的jad文件中缺少MicroEdition-Configuration和MicroEdition-Profile两个属性是不能成功转成cod文件的。这可以在工程的build.xml中的<build>属性里的<jad>元素中添加:

  Java代码

  • <jad>     <attribute target="jad" name="
    MicroEdition-Configuration"
     value="CLDC-1.1" 
  • if="polish.cldc11"/>     <attribute target="jad" 
    name=
    "MicroEdition-Profile" value="MIDP-2.0"/>    
  • </jad>

  •   四、如果你用了混淆器的(obfuscator),要把它unactivate,不要用它,因为BlackBerry中的rapc转换过程中会对程序混淆的。

      Java代码

  • <obfuscator name="ProGuard" unless="test or polish.blackberry" >    
  • </obfuscator>
  •   五、在工程的build.xml中的<Java MEpolish>属性requirements用你想编译的BlackBerryemulator,如:

      Java代码

  • <deviceRequirements>      
    <requirement name="Identifier" value="BlackBerry/8800" />              
  • </deviceRequirements>
  •   如果你的程序是一般的Java ME程序,那么就可以编译运行了。但如果你是用BlackBerry API开发的上海柱塞阀,就要就把build.xml里<build>元素中的<midlet>,改为<main>,同时要添加polish.classes.midlet-1的variable。如:

      Java代码

  • <!-- midlets definition -->   
    <main 
    class="com.protel.BlackBerryim.ui.BlackBerryIMMidlet" />     
  • <!-- project-wide variables - used for preprocessing  -->   
    <variables> <variable name=
    "polish.classes.midlet-1" value=" " />    
  • </variables>
  •   (注:polish.classes.midlet-1的value是" ",中间有一个空格的,我试过了,如果没有这个定义变量或者这个值中间没有空格,jar是不能转为cod格式。)

      这是我初接触BlackBerry时的一点心得。我用BlackBerry API在NetBeans+Java ME polish的环境下写过一个test app,是能成功运行的,希望对初接触BlackBerry的朋友有帮助。

     


     

    posted @ 2012-02-03 22:32 cangshi 阅读(363) | 评论 (0)编辑 收藏

    如何通过Java调用C/C++编写第三方dll动态链接库解决方案分析。
    最近在用weka做一个数据挖掘相关的项目,不得不说,weka还是一个不错的开放源代码库,提供了很多最常用的分类和聚类算法。

    在我的项目中要用到一个聚类算法,Affinity Propagation(AP),由多伦多大学的Brendan J. Frey发表于2007年。相比其他的聚类算法,AP算法的聚类结果更加准确。

    在AP的官方网站公布了AP算法的动态链接库,我的目标就是实现在Java工程中调用这个动态链接库。

    在网上查了资料,发现,如果仅仅是想调用Windows的Native API还是比较省事的,这里我主要针对第三方dll的调用。

    下面进入正题。

    这里主要用的方法是JNI。在网上查资料时看到很多人说用JNI非常的复杂,不仅要看很多的文档,而且要非常熟悉C/C++编程。恐怕有很多人在看到诸如此类的评论时已经决定绕道用其他方法了。但是,假如你要实现的功能并不复杂(简单的参数传递,获取返回值等等),我还是支持使用这个方法的。

    Java Native Interface,简称JNI,是Java平台的一部分,可用于让Java和其他语言编写的代码进行交互。下面是从网上摘取的JNI工作示意图。


    图1 JNI的工作模式

    下面就举具体的例子说明一下使用步骤:

    1) 编写一个类,声明native方法

    1. public class APCluster {   
    2.     public native int[] CallAPClusterDll( int         arg_Int,   
    3.                                           double[]    arg_DoubleArray,   
    4.                                           boolean     arg_boolean);  
    5.     static 
    6.     {  
    7.         System.loadLibrary("APClusterDllMedium");  
    8.     }  

    上面是APCluster.java文件,定义了一个APCluster类,其中有一个方法CallAPClusterDll(),需要传递三种不同类型的参数,并且返回一个整型数组。

    注意,这里只需要声明这个方法,并不需要实现,具体实现就在APClusterDllMedium中。

    APClusterDllMedium就像中介一样,Java通过调用这个中介Dll中的CallAPClusterDll方法,间接调用真正的第三方Dll。

    2)编译生成.h文件

    第一步:

    javac APCluster.java 生成APCluster.class

    第二步:

    javah APCluster 生成APCluster.h头文件,内容如下:

    1. /* DO NOT EDIT THIS FILE - it is machine generated */ 
    2. #include <jni.h>  
    3. /* Header for class APCluster */ 
    4. #ifndef _Included_APCluster  
    5. #define _Included_APCluster  
    6. #ifdef __cplusplus  
    7. extern "C" {  
    8. #endif10 /*  
    9.  * Class:     APCluster  
    10.  * Method:    CallAPClusterDll  
    11.  * Signature: (I[DZ)[I  
    12.  */ 
    13. JNIEXPORT jintArray JNICALL Java_APCluster_CallAPClusterDll  
    14.   (JNIEnv *, jobject, jint, jdoubleArray, jboolean);  
    15. #ifdef __cplusplus  
    16. }  
    17. #endif21
    18. #endif 

    注意,APCluster.h这个头文件的内容是不能修改的,否则JNI会找不到相对应的CallAPClusterDll()的实现。


    3)创建C/C++工程,实现CallAPClusterDll()方法。

    创建一个C/C++工程,工程名为APClusterDllMedium(其实,生成的dll名为APClusterDllMedium即可),导入APCluster.h这个头文件,并创建一个CPP文件,实现.h文件中的方法。

     
    图2 新建工程结构

    由于我创建的工程是win32控制台程序,所以最后默认生成的是.exe文件,所以还要做一步工程属性修改,让它生成.dll后缀文件。

    打开Project Property ->General,做以下修改:

     
    图3 修改工程属性

    下面就是实现 JNIEXPORT jintArray JNICALL Java_APCluster_CallAPClusterDll (JNIEnv *, jobject, jint, jdoubleArray, jboolean); 这个方法了。先贴代码再慢慢解释吧。

    1. #include "APCluster.h"   
    2. #include <stdio.h>   
    3. #include <windows.h>  
    4. #ifdef __cplusplus   
    5. extern "C" {  
    6. #endif  
    7. typedef int*  (__stdcall *APCLUSTER32)(double*, unsigned int, bool);  
    8. JNIEXPORT jintArray JNICALL Java_APCluster_CallAPClusterDll  
    9.   (JNIEnv *env, jobject _obj, jint _arg_int, jdoubleArray _arg_doublearray, jboolean _arg_boolean)  
    10. {  
    11.     HMODULE dlh = NULL;  
    12.     APCLUSTER32 apcluster32;  
    13.     if (!(dlh=LoadLibrary("apclusterwin.dll")))        //第三方DLL位置  
    14.     {  
    15.         printf("LoadLibrary() failed: %d\n", GetLastError());   
    16.     }  
    17.     if (!(apcluster32 = (APCLUSTER32)GetProcAddress(dlh, "apcluster32")))    //具体调用apcluster32方法  
    18.     {  
    19.         printf("GetProcAddress() failed: %d\n", GetLastError());   
    20.     }  
    21.     int        m_int = _arg_int;  //类型转换  
    22.     double*    m_doublearray = env->GetDoubleArrayElements(_arg_doublearray, NULL);  
    23.     bool       m_boolean = _arg_boolean;  
    24.     int* ret = (*apcluster32)(m_doublearray, m_int, m_boolean); /* actual function call */ 
    25.     jintArray result = env->NewIntArray(_arg_int);  
    26.     env->SetIntArrayRegion(result, 0, _arg_int, (const jint*)ret);  
    27.     FreeLibrary(dlh); /* unload DLL and free memory */ 
    28.     if(ret)   
    29.     {  
    30.          free(ret);   
    31.     }  
    32.     return result;  
    33. }  
    34. #ifdef __cplusplus  
    35. }  
    36. #endif 

    a)首先为了#include <jni.h>,必须添加JNI所在的目录。

    打开Project Property -> C/C++ -> General -> Additional Include Directories添加相应目录:

     
    图4 添加JNI目录

    b)在APCluster.h文件中自动生成的函数,只标识了函数参数类型,为了引用这些参数,自己起一个相应的名字:

    JNIEXPORT jintArray JNICALL Java_APCluster_CallAPClusterDll
    (JNIEnv *env, jobject _obj, jint _arg_int, jdoubleArray _arg_doublearray, jboolean _arg_boolean) ......

    c)声明函数指针,就是你要调用的第三方dll中函数的类型。

    d)LoadLibrary,导入真正的第三方Dll,并找到要调用的方法的函数地址。

    把这个函数地址赋值给函数指针,接下来就可以通过这个函数指针调用真正的apcluster函数了!

    e)类型转换:

    读读jni.h文件就知道jdouble和double其实是一个东西,jboolean就是unsigned char类型,jni.h中是这么声明的:

    1. typedef unsigned char    jboolean;  
    2. typedef unsigned short   jchar;  
    3. typedef short            jshort;  
    4. typedef float            jfloat;  
    5. typedef double           jdouble; 

    但是数组类型就没有这么简单,获取数组要使用类型相对应的env->GetTypeArrayElement(jTypeArray...)。

    最后,要返回一个jint类型的数组,就要新创建一个此类型的数组,再为其赋值:

    1. jintArray result = env->NewIntArray(_arg_int);  
    2. env->SetIntArrayRegion(result, 0, _arg_int, (const jint*)ret); 

    其中,_arg_int代表的是创建数组的长度。

    最后return result。

    4)Build这个工程。

    Build,生成相应的APCluster.dll文件,将这个dll放到java工程目录下。

     
    图5 将生成的dll放到java工程下

    5)编写测试java程序,调用dll库。

    以下为测试程序,Test.java:

    1. public class Test    
    2. {  
    3.     public static void main(String[] args)   
    4.     {   
    5.         double     arg_doublearray[] = {0.10.20.3};   
    6.         int        arg_int = 3;   
    7.         boolean    arg_boolean = true;   
    8.         int[]  result = new APCluster().CallAPClusterDll(arg_int, arg_doublearray, arg_boolean);  
    9.         .....  
    10.     }  

    到此,java调用第三方dll就基本完成了。

    本文也主要是介绍大概的操作流程,至于具体应该使用哪些API就只有去研究官方文档了。

    另外还有一些需要注意的问题,比如64位的程序去调用32位的dll会报错啊等等...这些都是细节问题了。

    最后,个人认为,自己动手实践还是很重要,网上都说这个复杂那个难,但是至于难还是不难,还是要实践了才知道...不能不去尝试...

    posted @ 2012-02-02 22:44 cangshi 阅读(1119) | 评论 (0)编辑 收藏

    仅列出标题
    共3页: 上一页 1 2 3