Отражение для поля идет не так - PullRequest
4 голосов
/ 01 июня 2010

Я пытался использовать отражение для определенного поля в классе android.os.build, поле MANUFACTURER ... Я пытался с помощью этого кода:

try
    {
        Class myBuildClass = android.os.Build.class;
        Field m1 = Build.class.getDeclaredField("MANUFACTURER");
        validField = true;

        manufacturer = Build.MANUFACTURER;
    }
    catch(Exception ex)
    {
        manufacturer = Build.PRODUCT;
        System.err.println("getDeviceSpecifics, got an exception during getting Field : " + ex.toString());
    }

Я получаю следующие ошибки:

06-01 11:26:37.639: WARN/dalvikvm(7342): VFY: unable to resolve static field 2 (MANUFACTURER) in Landroid/os/Build;
06-01 11:26:37.639: WARN/dalvikvm(7342): VFY:  rejecting opcode 0x62 at 0x0048

06-01 11:26:37.639: WARN/dalvikvm(7342): VFY:  rejected Lmypackage/android/managementModule/Management;.getDeviceSpecifics ()V
06-01 11:26:37.639: WARN/dalvikvm(7342): Verifier rejected class Lmypackage/android/managementModule/Management;

И при отладке я заметил, что InvocationtargetException постоянно генерируется, так что, полагаю, я неправильно реализовал весь принцип Reflection ... Есть идеи, где что-то идет не так или нет, как правильно реализовать Refelction для одного поля?

Ответы [ 7 ]

3 голосов
/ 24 сентября 2010

Идеальное решение

try // reflection
  {
   Field manufacturerField = android.os.Build.class
     .getDeclaredField("MANUFACTURER");
   manufacturerField.setAccessible(true);
   String manufacturerName = manufacturerField.get(
     android.os.Build.class).toString();
   System.out.println("manufacturerName: " + manufacturerName);

  } catch (Exception ex) {

   System.err
     .println("getManufacturerName, got an exception during getting Field : "
       + ex.toString());
  }
1 голос
/ 01 июня 2010

Это поле является публичным. Вам не нужно размышление, чтобы прочитать это.

Но в вашем коде есть несколько проблем, которые вызывают эту ошибку:

Class myBuildClass = android.os.Build.class;
Field m1 = Build.class.getDeclaredField("MANUFACTURER");

Вы определяете myBuildClass, но позже вы его никогда не используете. То же самое для поля m1. И после этого вы просто получаете к нему прямой доступ по телефону

Build.MANUFACTURER;

Тогда для чего используется весь материал отражения?

Если это будет приватно, вы делаете это следующим образом:

Field manufacturer = android.os.Build.class.getDeclaredField("MANUFACTURER");
manufacturer.setAccessible(true);
int myManufacturer = manufacturer.getInt(android.os.Build.class);

Примечание: factoryr.getInt (android.os.Build.class) возможен только потому, что это статическое поле. В противном случае вам нужно будет передать фактический объект этого класса.

Я видел в ваших комментариях, что вы хотите проверить, доступно ли поле. Поле всегда будет доступно, но время от времени оно может иметь разные значения. Почему он не должен быть доступен?

Хорошо, теперь я также видел в ваших комментариях, что вы хотите сделать это для 1.6. Посмотрите документацию , и вы увидите, что это поле было добавлено на уровне API 1.4.

Ваш код может работать в версии 1.6, но я должен упомянуть, что считаю его действительно ненужным и отчасти также неправильным.

0 голосов
/ 16 июля 2010

У меня была проблема с симуляцией, вот соответствующий фрагмент, с которым я играл:

try {
    return android.os.Build.class.getField("MANUFACTURER").get(null).toString();
} catch (Exception e) {
    return "???";
}
0 голосов
/ 02 июня 2010

@ Себи, настоящим весь код, я поместил его как «ответ», потому что размещение кода в этих комментариях довольно нечитабельно

String manufacturer;
try //reflection
        {
            Field manufacturerField = android.os.Build.class.getDeclaredField("MANUFACTURER");
            manufacturerField.setAccessible(true);
            int myManufacturer = manufacturerField.getInt(android.os.Build.class);
            manufacturer = Build.MANUFACTURER;
        }
        catch(Exception ex)
        {
            manufacturer = Build.PRODUCT;

        System.err.println("getDeviceSpecifics, got an exception during getting Field : " + ex.toString());
    }

Это не работает на моем устройстве 1.5. Это потому, что линия

manufacturer = Build.MANUFACTURER;

есть, так что если он пропущен, как в:

 try    //reflection
    {
        Field manufacturerField = android.os.Build.class.getDeclaredField("MANUFACTURER");
        manufacturerField.setAccessible(true);
        int myManufacturer = manufacturerField.getInt(android.os.Build.class);
    }
    catch(Exception ex)
    {
        manufacturer = Build.PRODUCT;

        System.err.println("getDeviceSpecifics, got an exception during getting Field : " + ex.toString());
    }

Это на самом деле будет работать, проблема, очевидно, заключается в том, что мне также нужна эта единственная строка в моем коде, чтобы на устройстве 1.6 я мог получить производителем

Кстати, я только что проверил все предложения на устройстве 1.5 и эмуляторе 1.5, и они оба выдают ошибки, забавно то, что даже самый короткий код в конструкции try-catch все равно выдаст

06-02 09:26:54.741: ERROR/AndroidRuntime(782): Uncaught handler: thread main exiting due to uncaught exception
06-02 09:26:54.791: ERROR/AndroidRuntime(782): java.lang.VerifyError: mypackage.android.Reflection.reflectiontest
0 голосов
/ 02 июня 2010

Не проще ли сначала проверить версию SDK, а не искать поле через отражение?

if (Build.VERSION.SDK_INT >= 4) {
    return Build.MANUFACTURER;
} else {
    return Build.PRODUCT;
}
0 голосов
/ 02 июня 2010

Прочитав комментарии к другим вопросам, теперь я понимаю, почему нельзя просто получить прямой доступ к полю. Потому что ваш код может работать под Android до версии 4.0.

Тем не менее, я не думаю, что отражение необходимо. Как насчет

try
{
     Build . MANUFACTURER ;
     // do stuff with Build . MANUFACTURER 
}
catch ( AppropriateException )
{
     // pre version 4.0 Contingency Plan
}
0 голосов
/ 01 июня 2010

Если вы посмотрите документы API, вы увидите, что Build.Manufacturer доступен только с уровня API 4. Это означает, что если вы запустите свой код на устройстве Android версии API 3 или ниже, он потерпит неудачу, поскольку это поле не существует.

...