2

我正在尝试在我的 android 应用程序中使用ICU-Project.org 库(ICU4J v55.1),它具有 Java 日历的绝佳替代品,例如日语和伊斯兰日历,但 jar 文件总是导致 eclipse 或我的应用程序崩溃

我不能在我的 android 应用程序中使用它,但它在普通的 Java 项目中可以 100% 正常工作,所以我不知道这是什么问题

第一次,我将 jar 文件复制到我的 lib 文件夹,然后右键单击 > 添加到构建路径

当我在 Android 模拟器中运行应用程序时,此方法会导致 IDE 被杀,并显示以下消息:

Unable to execute dex: Java heap space
Java heap space

虽然我增加了堆空间,如下所示,但没有解决:

--launcher.XXMaxPermSize
2048M
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
2048m
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vmargs
-Dosgi.requiredJavaVersion=1.6
-Xms2048m
-Xmx2048m

第二次:我已经删除了 jar 文件,并从中添加它(右键单击 MyApp > properties > Java Build Path > Libraries tab > add external jars

在 Order and Export 选项卡中,jar 未选中

现在,当我运行 Android Emulator 时,它可以工作,但我的应用程序崩溃并出现以下错误:

08-27 18:46:06.635: I/dalvikvm(295): Could not find method com.ibm.icu.util.Calendar.getInstance, referenced from method com.c.cx.Main.onCreate
08-27 18:46:06.635: W/dalvikvm(295): VFY: unable to resolve static method 13898: Lcom/ibm/icu/util/Calendar;.getInstance ()Lcom/ibm/icu/util/Calendar;
08-27 18:46:06.665: D/dalvikvm(295): VFY: replacing opcode 0x71 at 0x0009
08-27 18:46:06.665: D/dalvikvm(295): VFY: dead code 0x000c-002b in Lcom/c/cx/Main;.onCreate (Landroid/os/Bundle;)V
08-27 18:46:06.805: D/AndroidRuntime(295): Shutting down VM
08-27 18:46:06.805: W/dalvikvm(295): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
08-27 18:46:06.815: E/AndroidRuntime(295): FATAL EXCEPTION: main
08-27 18:46:06.815: E/AndroidRuntime(295): java.lang.NoClassDefFoundError: com.ibm.icu.util.Calendar
08-27 18:46:06.815: E/AndroidRuntime(295):  at com.c.cx.Main.onCreate(Main.java:15)
08-27 18:46:06.815: E/AndroidRuntime(295):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
08-27 18:46:06.815: E/AndroidRuntime(295):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
08-27 18:46:06.815: E/AndroidRuntime(295):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
08-27 18:46:06.815: E/AndroidRuntime(295):  at android.app.ActivityThread.access$2300(ActivityThread.java:125)
08-27 18:46:06.815: E/AndroidRuntime(295):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
08-27 18:46:06.815: E/AndroidRuntime(295):  at android.os.Handler.dispatchMessage(Handler.java:99)
08-27 18:46:06.815: E/AndroidRuntime(295):  at android.os.Looper.loop(Looper.java:123)
08-27 18:46:06.815: E/AndroidRuntime(295):  at android.app.ActivityThread.main(ActivityThread.java:4627)
08-27 18:46:06.815: E/AndroidRuntime(295):  at java.lang.reflect.Method.invokeNative(Native Method)
08-27 18:46:06.815: E/AndroidRuntime(295):  at java.lang.reflect.Method.invoke(Method.java:521)
08-27 18:46:06.815: E/AndroidRuntime(295):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
08-27 18:46:06.815: E/AndroidRuntime(295):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
08-27 18:46:06.815: E/AndroidRuntime(295):  at dalvik.system.NativeStart.main(Native Method)

我对lib的使用:

package com.c.cx;

import com.ibm.icu.util.Calendar;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;

public class Main extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Calendar cal = Calendar.getInstance();      
        Toast.makeText(getApplicationContext(), ""+cal.get(Calendar.YEAR), Toast.LENGTH_SHORT).show();

    }

}

我的 JDK 版本:1.6,我已将其更改为 1.7,但没有解决。

请在您判断之前尝试一下。

4

1 回答 1

1

好吧,ICU 主要不是为 Android 设计的。尤其是有两点让我担心:

我也不确定使用类加载器在 jar 中加载资源是否在 Android 平台上是一种有效的机制。其他库已观察到与此主题相关的性能问题 - 例如Joda-Time-Android(尤其是“为什么使用此库?”部分)或Threeten-ABP。我有足够的理由克隆我自己的名为 Time4J/A 的库,并将其重新架构为优化的 aar 库,使用资产文件作为资源。

关于你说ICU的伊斯兰日历“精彩”。我敢有不同的意见。就像在 Joda-Time 中一样,ICU 的伊斯兰变体只是一种算法近似,但不能取代像沙特阿拉伯的 umalqura-calendar 这样的基于目击的变体。

更正:现在我看到 ICU 还声称从 v52 版本开始支持 Umalqura(只知道旧版本)。所以 ICU 对伊斯兰日历的支持确实比大多数其他库更好。

2015 年 8 月 31 日更新:

现在我回答的积极部分(第一部分相当消极 - 抱歉)。今天我发布了Time4A-v3.6-2015f。它包含一个回历日历,涵盖了 ICU4J 支持的所有变体。例子:

PlainDate today = SystemClock.inLocalView().today();
System.out.println(today); // 2015-08-31

HijriCalendar hijri = // conversion on local timeline at noon
  today.transform(HijriCalendar.class, HijriCalendar.VARIANT_ICU4J);
System.out.println(hijri); // AH-1436-11-17[islamic-icu4j]

反向转换为公历日期很简单:

System.out.println(hijri.transform(PlainDate.class));

请注意,Umalqura 将显示 1436-11-16。ICU 日历类型映射如下:

HijriCalendar.VARIANT_ICU4J => 伊斯兰日历.CalculationType.ISLAMIC

HijriCalendar.VARIANT_UMALQURA => 伊斯兰日历.CalculationType.ISLAMIC_UMALQURA

HijriAlgorithm.WEST_ISLAMIC_CIVIL => 伊斯兰日历.CalculationType.ISLAMIC_CIVIL

HijriAlgorithm.WEST_ISLAMIC_ASTRO => 伊斯兰日历.CalculationType.ISLAMIC_TBLA

使用 ISLAMIC 进行天文 ICU-Simulation 的基础数据没有在 Time4J 中重新计算,而是使用简单的传输代码工具(基于 ICU4j)进行了计算,例如:

IslamicCalendar cal = new IslamicCalendar(TimeZone.GMT, Locale.ROOT);
cal.clear();
cal.setCalculationType(IslamicCalendar.CalculationType.ISLAMIC);

for (int hyear = 1; hyear <= 1600; hyear++) {[
  cal.set(Calendar.YEAR, hyear);
  // here writing the islamic year in a data-file
  for (int hmonth = 1; hmonth <= 12; hmonth++) {
    cal.set(Calendar.MONTH, hmonth - 1); // zero-based-index
    cal.set(Calendar.DAY_OF_MONTH, 1);
    int len = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
    if (hmonth > 1) {
      // write a space into the file
    }
    // write the length of month in days
  }
}

此代码确保 Time4J 在 1-1600 年范围内管理与 ICU4J 完全相同的数据。所以你应该可以用 Time4A (大约 724kB 的 AAR 库)替换 ICU4J。我已经在 Android Studio 模拟器上测试过了。你真的不需要害怕失去 i18n 的能力。Time4A 支持 45 种语言,包括阿拉伯语、波斯语等伊斯兰时代和伊斯兰月份的名称(基于 CLDR-26)。格式化示例显示在online-javadoc中。

于 2015-08-28T10:11:26.243 回答