从前面的分析 中,我们可以知道JAD(Java Application Descriptor)文件是一个外 部 (相对JAR文件)描述文件,而Manifest.mf是一个内部 列表文件。他们对于AMS的运 行都起着至关重要的作用。
虽然它们的命名或者说文件类型都比较让人费解,不过,实际上它们也不过是单纯的文本文件 ,形式上非常相似,都 是:“属性名称:属性值 ”。
这些属性主要包括:
属性名称
属性说明
Manifest.mf
JAD
MIDlet-Name
MIDlet Suite的名称
必需
必需
MIDlet-Version
MIDlet Suite的版本号
必需
必需
MIDlet-Vendor
MIDlet Suite的作者
必需
必需
MIDlet-n
属于该MIDlet Suite的每一个MIDlet都应独立定义一个
必需
必需
MicroEdition-Profile
MIDlet Suite所需简表版本
必需
必需
MicroEdition-Configuration
MIDlet Suite所需配置版本
必需
必需
MIDlet-Jar-URL
对应JAR文件的下载地址
-
必需
MIDlet-Jar-Size
JAR文件大小,单位:字节
-
必需
MIDlet-Description
MIDlet Suite的描述
可选
可选
MIDlet-Icon
MIDlet Suite的图标路径
可选
可选
MIDlet-Info-URL
MIDlet Suite的信息路径
可选
可选
MIDlet-Data-Size
MIDlet Suite用于持久性存储所需的最小字节数
可选
可选
MIDlet-Permission(MIDP2.0)
MIDlet Suite需要访问的受限API的许可
可选
可选
MIDlet-Permissions-Opt(MIDP2.0)
定义那些访问受限API非关键的许可
可选
可选
MIDlet-Push(MIDP2.0)
Push注册
可选
可选
MIDlet-Install-Notify(MIDP2.0)
定义接收MIDlet Suite安装状态的URL
可选
可选
MIDlet-Delete-Notify(MIDP2.0)
定义接收MIDlet Suite删除报告的URL
可选
可选
MIDlet-Delete-Confirm(MIDP2.0)
MIDlet Suite确认删除的提示信息
可选
可选
再分别看一个典型的Manifest.mf文件和JAD文件究竟是怎么定义:
“Manifest.mf”
MIDlet-1: CustomItem, customitemdemo.png, customitem.CustomItemDemo
MIDlet-10: Ticker, tickerdemo.png, ticker.TickerDemo
MIDlet-2:
StringItem, stringitemdemo.png, stringitem.StringItemDemo
MIDlet-3:
Gauge, gaugedemo.png, gauge.GaugeDemo
MIDlet-4: Alert,
alertdemo.png, alert.AlertDemo
MIDlet-5: ChoiceGroup,
choicegroup.png, choicegroup.ChoiceGroupDemo
MIDlet-6: List,
listdemo.png, list.ListDemo
MIDlet-7: TextBox,
textboxdemo.png, textbox.TextBoxDemo
MIDlet-8: TextField,
textfielddemo.png, textfield.TextFieldDemo
MIDlet-9:
DateField, datefielddemo.png, datefield.DateFieldDemo
MIDlet-Description:
Basic UI elements functionality demo.
MIDlet-Name: UIDemo
MIDlet-Vendor: Sun Microsystems, Inc.
MIDlet-Version:
1.0
MicroEdition-Configuration: CLDC-1.0
MicroEdition-Profile:
MIDP-2.0
“UIDemo.jad”
MIDlet-1: CustomItem, customitemdemo.png, customitem.CustomItemDemo
MIDlet-10: Ticker, tickerdemo.png, ticker.TickerDemo
MIDlet-2:
StringItem, stringitemdemo.png, stringitem.StringItemDemo
MIDlet-3:
Gauge, gaugedemo.png, gauge.GaugeDemo
MIDlet-4: Alert,
alertdemo.png, alert.AlertDemo
MIDlet-5: ChoiceGroup,
choicegroup.png, choicegroup.ChoiceGroupDemo
MIDlet-6: List,
listdemo.png, list.ListDemo
MIDlet-7: TextBox,
textboxdemo.png, textbox.TextBoxDemo
MIDlet-8: TextField,
textfielddemo.png, textfield.TextFieldDemo
MIDlet-9:
DateField, datefielddemo.png, datefield.DateFieldDemo
MIDlet-Description:
Basic UI elements functionality demo.
MIDlet-Jar-Size: 22798
MIDlet-Jar-URL: UIDemo.jar
MIDlet-Name: UIDemo
MIDlet-Vendor: Sun Microsystems, Inc.
MIDlet-Version: 1.0
MicroEdition-Configuration: CLDC-1.0
MicroEdition-Profile:
MIDP-2.0
置于每个属性对应的属性值应该怎么定义(如MIDlet-n,MIDlet-Version的属性值的格式),这里不做介绍,具体可以参考MIDP 的相关说明。
根据MIDP的规定,代表MIDlet Suite的JAR文件内部要有一个列表文件,且文件名为Manifest.mf 。
JAD文件虽然是可选的,但是也很有用武之地,特别是,在OTA模式下,在MIDlet Suite安装到移动设备之前,AMS首先会读取JAD文件的内容,分析MIDlet Suite是否与设备实现兼容,最典型的就是分析配置和简表的版本是否匹配。如果不兼容,那么AMS就会拒绝安装。这样也符合用户的需求。
同时,使用JAD文件的另一个优势是,可以自定义属性 ,比如说定义一个web服务的请求URL,当URL改变 时,我们就不需要改变JAR的内部文件,来适应变更。
MIDlet-1: Query, Query.png, client.QMIDlet
……
queryURL:
http://localhost:8080/QServlet/query.do
仔细观察上表,对于Manifest.mf文件和JAD文件来说三个属性是必须的:MIDlet-Name,MIDlet- Version和MIDlet-Vendor 。三者属性值必须保持一致,否则AMS将不会下载和安装这个MIDlet Suite。而对于MIDlet-n,MicroEdition-Profile和MicroEdition-Configuration属性,实际上并 不需要在JAD文件和Manifest.mf文件中重复定义。
另外,当用户安装MIDlet Suite的时候,AMS会鉴别正在安装的MIDlet Suite是被信任的(Trusted)还是非信任的(Untrusted)。根据MIDlet Suite类型的不同,AMS处理在这两个文件中被重复定义的属性也采取了不同的方法:
- 当为Trusted 时:如果定义的属性在Manifest.mf和JAD文件中都出现,那么它们必 须保持一致 。
- 当为Untrusted 时:如果定义的属性在Manifest.mf和JAD文件中都出现,那么MIDlet 在运行时期所取得属性值则以JAD文件中的定义的为准 。
属性定义知道了,那么怎么来获取它们的属性值呢?其实很简单,上面所提到的属性值,几乎所有都可以通过javax.microedition.mdilet.MIDlet.getAppProperty() 这 个方法来获取,唯独MicroEdition-Configuration 和MicroEdition-Profile 需 要是通过java.lang.System.getProperty() 来获取的。
最后还有一点值得指出的是:中文问题 。把在Manifest.mf和JAD文件中出现的中文字符转换为 Unicode的正则表达式可以有效防止乱码。
转换的方法是利用JDK所提供的native2ascii.exe 工具。
CMD命令:
native2ascii 源文件.txt 目标文件.txt
转换前:MIDlet-1: 中文字典, DicMIDlet
转换后:MIDlet-1: \u4e2d\u6587\u5b57\u5178, DicMIDlet
转载:http://www.deepzhu.cn/2009/11/08/archives/57
注意事项:先注册一个locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
1000, 0, locationListener); 在成功注册了一个周期性坐标更新以后,我们就随时可以通过下面的方法来取得当前的坐标了,要不然就会有loc空指针
Android中LocationManager的提供了一系列方法来地理位置相关的问题,包括查询上一个已知位置;注册/注销来自某个 LocationProvider的周期性的位置更新;以及注册/注销接近某个坐标时对一个已定义Intent的触发等。今天我们就来看看Android 中LocatinManager的简单使用,以获取当前所在的位置为例。
首先,我们需要获取LocationManager的一个实例,这里需要注意的是他的实例只能通过下面这种方式来获取,直接实例化LocationManager是不被允许的。
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
得到了LocationManager的实例locatonManager以后,我们通过下面的语句来注册一个周期性的位置更新。
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
1000, 0, locationListener);
这句代码告诉系统,我们需要从GPS获取位置信息,并且是每隔1000ms更新一次,并且不考虑位置的变化。最后一个参数是LocationListener的一个引用,我们必须要实现这个类。
private final LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) { //当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发
// log it when the location changes
if (location != null) {
Log.i("SuperMap", "Location changed : Lat: "
+ location.getLatitude() + " Lng: "
+ location.getLongitude());
}
}
public void onProviderDisabled(String provider) {
// Provider被disable时触发此函数,比如GPS被关闭
}
public void onProviderEnabled(String provider) {
// Provider被enable时触发此函数,比如GPS被打开
}
public void onStatusChanged(String provider, int status, Bundle extras) {
// Provider的转态在可用、暂时不可用和无服务三个状态直接切换时触发此函数
}
};
以上的这些步骤一般应当在Activity的onCreate()阶段完成。
在成功注册了一个周期性坐标更新以后,我们就随时可以通过下面的方法来取得当前的坐标了。
Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
double latitude = location.getLatitude(); //经度
double longitude = location.getLongitude(); //纬度
double altitude = location.getAltitude(); //海拔
不过这时候,如果你尝试去运行这个LocationSample的话程序启动时多半就会报错,因为我们没有设置GPS相关的权限,解决方法也相当简单,在 AndroidManifest.xml中的block里添加下面这句即可解决权限的问题。详细的权限设置,请参考官方文档docs/reference /android /Manifest.permission.html
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
some_activity.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> // some views <include layout="@layout/view_part"/> // probably more views </LinearLayout>
view_part.xml:
<merge xmlns:android="http://schemas.android.com/apk/res/android"> // the views to be merged </merge>
2
public void saveFormality() { try { ContentValues values = new ContentValues(); values.put(Data.DATA1, this.getFormality() ? "1" : "0"); int mod = ctx.getContentResolver().update( Data.CONTENT_URI, values, Data.CONTACT_ID + "=" + this.getId() + " AND " + Data.MIMETYPE + "= '" + clsContacts.FORMALITY_MIMETYPE + "'", null); if (mod == 0) { values.put(Data.CONTACT_ID, this.getId()); values.put(Data.MIMETYPE, clsContacts.FORMALITY_MIMETYPE); ctx.getContentResolver().insert(Data.CONTENT_URI, values); } } catch (Exception e) { Log.v(TAG(), "saveFormality failed"); } }