Android, UTF8 - Как я могу убедиться, что UTF8 используется для общего предпочтения - PullRequest
4 голосов
/ 10 февраля 2012

Как мне убедиться, что UTF8 используется для общего меню настроек? У меня есть меню настроек Android, которое позволяет пользователю, среди прочего, установить свое имя.

Мне нужно знать, как преобразовать данные, хранящиеся в общих настройках, в формат UTF8

Меню настроек расположено в формате xml с использованием кодировки utf8 в файле с названием settings в папке res / xml и выглядит следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android">
    <EditTextPreference
        android:key="@string/name_key"
        android:title="@string/hof_name_title"
        android:summary="@string/hof_name_summary"
        android:defaultValue="Anonymous" />
    <CheckBoxPreference
        android:key="@string/new_game_preference_key"
        android:title="@string/new_game_preference_title"
        android:summary="@string/new_game_preference_summary"
        android:defaultValue="false" />
</PreferenceScreen>

Класс, который обрабатывает это

public class PrefsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.settings);
    }

    @Override
    protected void onPause() {
        super.onPause();
        // Unregister the listener whenever a key changes
        getPreferenceScreen().getSharedPreferences()
                .unregisterOnSharedPreferenceChangeListener(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        // Set up a listener whenever a key changes
        getPreferenceScreen().getSharedPreferences()
                .registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
            String key) {
//      Util.log_debug_message("@@@@ Changed prefrence key = " + key);
        if (key.equalsIgnoreCase(getString(R.string.name_key))){
            update_webserver();
        }else if (key.equalsIgnoreCase(getString(R.string.new_game_preference_key))){
            update_webserver();
        }
    }

    protected void update_webserver(){
        Intent webServerReg = new Intent(this, RegService.class);
        webServerReg.putExtra(Config.C2DM_REG_ID_EXTRA, C2DMessaging.getRegistrationId(this));
        startService(webServerReg);     
    }
}

Я предполагал, что настройка <?xml version="1.0" encoding="utf-8"?> будет гарантировать, что текст будет закодирован в формате UTF8, но это не всегда так. Я получаю значения во всех видах форматов. Некоторые примеры

"\ nFe \ xF1a", "L \ xFAcia", "$ '\ xE5 \ xEE'",

или

": - $ B-) O: -): - P = -ob -): - D: -Q: -X: -: - |! \ П: '(: - * XDo_O: -X: -C: -X: О: -X = -O; -): -): -); -): - D: OX- (о_О: -V: - @: - V: -X: -Do_O :: -С \ XBF \ xÀ1 \ xÀ1 \ XAB \ Xbb \ XAE \ xÀ9 ^ \ xA5 \ xA5? [\ XÀ2}? \ XÀ2 \ xÀ2 \ xA5 \ XA3? $ \ XBF \ xÀ1 \ XAE \ xA7> <[\ XA3 ~? = ~~ <code>\xB0]\xA3?\xA7\xA1\\\xAB\xBB\xAE^``]]||||}{_|] ||| \ XB0 \ XB0? "

Да, это последний набор рубинов в последнем примере.

Проблемы, которые возникают у меня при попытке отправить nmes в виде запроса HTTP POST или PUT json на мой веб-сервер, используя следующий код

public void update(String regId) throws AuthenticationException {
    JSONObject mu_to_send = createJsonToPost(regId, false);
    HttpResponse response;
    try {
        response = HttpRequest.httpPutJSONObject(this,
                Config.UPDATE_USER_URL, mu_to_send);
        int responseCode = response.getStatusLine().getStatusCode();
        String responseJson;
        try {
            responseJson = EntityUtils.toString(response.getEntity());
            String msg = "";

            if (responseCode == 201) {
                // mobile_user = new
                // JSONObject(responseJson).getJSONObject("mobile_user");
                // Broadcast.sendBroadcast(this,
                // ResponseReceiver.ACTION_RESP,
                // Intent.CATEGORY_DEFAULT, Config.C2DM_MESSAGE_EXTRA,
                // Config.BROADCAST_WEBSERVER_USER_CREATED);
            } else {
                msg = "Failed to register with server! HTTP response code = "
                        + responseCode;
            }
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    } catch (ClientProtocolException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

}

public JSONObject createJsonToPost(String regId, boolean set_password) {
    JSONObject holder = new JSONObject();
    JSONObject data = new JSONObject();
    try {
        data.put("auth", regId);
        data.put("name", C2DMessaging.getName(this));
        data.put("receive_new_game_notification",
                C2DMessaging.getGameStartedNotificationPreference(this));
        holder.put("mobile_user", data);
    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return holder;
}

public static HttpResponse httpPutJSONObject(Context context, String url,
        JSONObject data) throws ClientProtocolException, IOException,
        AuthenticationException {
    DefaultHttpClient httpclient = getHttpClient(context);
    HttpPut httpput = new HttpPut(url);
    httpput.addHeader("User-Agent", Config.USER_AGENT);
    httpput.addHeader("Accept", "application/json");
    httpput.addHeader("Content-type", "application/json");
    httpput.addHeader(new BasicScheme().authenticate(
            getCredentials(context), httpput));
    StringEntity se = new StringEntity(data.toString());

    httpput.setEntity(se);
    return httpclient.execute(httpput);
}

Это вызывает всевозможные проблемы на моем веб-сервере, которые ожидают допустимый JSON (т.е. UTF8) в первую очередь JSON следует отправлять в кодировке UTF8.

So

1) Почему <?xml version="1.0" encoding="utf-8"?> фактически не устанавливает кодировку UTF8? когда используется в макете?

2) Как сделать так, чтобы на мой веб-сервер всегда отправлялись действительные символы формата UTF8? Должно ли это быть обработано запросом put или кодом, который сохраняется в общем предпочтении, или кодом, который заполняет объект json, или, возможно, комбинацией вышеупомянутого ? или что-то еще?

Это продолжение вопроса RoR Rails 3 - Как обрабатывать PG Ошибка неполного многобайтового символа

1 Ответ

2 голосов
/ 04 января 2013

Ключ к пониманию разницы между UTF-8 и Unicode .

  • Java обрабатывает символы и строки в памяти с использованием Unicode.Каждый символ хранится в двух байтах.
  • Когда текст передается между процессами (например, на веб-сервер) или , он записывается / читается с диска, внутреннее представление преобразуется вформат проводной связи.Это кодировка или декодирование.UTF-8 является самым популярным, но другие форматы включают в себя:
    • UTF-16
    • ISO 8859-1

В вашем вопросеВы упоминаете, что файлы XML кодируются в utf-8: это хорошо, и вы сможете помещать в файлы посторонние символы, но это определяет кодировку только для этого конкретного файла XML .

Эти XML-файлы будут скомпилированы в ресурсы Android и будут содержать правильные значения (вы можете проверить это, если хотите, в отладчике или сохранив промежуточные файлы ресурсов Java из цепочки сборки).

Проблема почти наверняка заключается в том, что вы отправляете данные и получаете данные с HTTP-сервера, особенно когда эти данные преобразуются между байтами в сети и Java String.В настоящее время вы не устанавливаете его в запросе - это можно сделать, как описано в документации для Apache HTTPClient .

Хотя сервер может уже потребовать / предположить это, это, безусловно, хорошая вещьчетко указать в запросе.

Вам также необходимо убедиться, что сервер (тот, что в Rails 3 - Как обрабатывать PG Ошибка неполного многобайтового символа ):

  • Ожидает UTF-8
  • Декодирует запрос, используя декодер UTF-8
  • Кодирует ответ, используя кодировку UTF-8

(Извините, ноЯ не знаю Ruby on Rails, поэтому не знаю, как конкретно там помочь).

Вернемся к концу Android, вам также нужно убедиться, что ваша библиотека HTTP декодирует ответ с помощью UTF-8 декодер.Если вы справитесь с этим самостоятельно, убедитесь, что используется используемый вами конструктор String, а аргумент - "utf-8":

Как только клиент, так и сервер используют UTF-8, ваши проблемы будут решены.

Чтобы помочь при отладке, я предлагаю:

  1. Количество операторов ведения журнала на сервере и клиенте, которые печатают соответствующие строки как можно ближе к коду HTTP
  2. Запуск с клиентом, настроенным для разговора черезотладка прокси.Изучите запрос и ответ и убедитесь, что это действительно UTF-8.Прокси включают в себя:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...