снова: Android MQTT не может создать клиент

Я пытаюсь создать MqttClient в Android, используя эмулятор Android (Nexus7) в ADT (Eclipse 3.8.0 в Linux Fedora17. Я нашел ответ на этот вопрос (Android MQTT не удалось создать клиент), но это не помогло решить мою проблему.

Я создал действие, которое позволяет пользователю войти в каталог, в котором хранится файл сохранения, но нет способа избежать исключения. Я пробовал с "/mnt/sdcard/", "/mnt/", "/mnt/sdcard/tmp/" и подобными.

Нужно ли обращать внимание на определенные настройки в эмуляторе Android в проекте Eclipse? Есть ли какие-либо разрешения на использование, которые должны быть включены в приложение?

Я просмотрел различные ресурсы mqtt, упомянутые в цитируемом вопросе с ответом, но мне не удалось найти ответ.

Это мой код:

package com.storassa.android.mqttsample;

import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttDefaultFilePersistence;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.TextView;

public class MqttSample extends Activity {

    Button okButton = null;
    AutoCompleteTextView inputTextView = null;
    TextView errorTextView = null;

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

        okButton = (Button)findViewById(R.id.okButton);
        inputTextView = (AutoCompleteTextView)findViewById(R.id.InputText);
        errorTextView = (TextView)findViewById(R.id.errorText);

        okButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                try {
                    String dir = inputTextView.getText().toString();
                    MqttDefaultFilePersistence mdfp = new MqttDefaultFilePersistence(
                            dir);
                    MqttClient client = new MqttClient("tcp://127.0.0.1:1833",
                            "0001", mdfp);
                }
                catch (Exception e) {
                    String errorText = "";
                    for (StackTraceElement error : e.getStackTrace())
                        errorText += error.toString() + "\n";
                    errorTextView.setText(errorText);
                }
            }
        });


    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_mqtt_sample, menu);
        return true;
    }

}

и это стек:

MqttException(0) at
org.eclipse.paho.client.mqttv3.MqttDefaultFilePersistence.open(MqttDefaultFilePersistence.java:74)
org.eclipse.paho.client.mqttv3.MqttClient.<init>(MqttClient.java:183)
com.storassa.android.mqttsample.MqttSample$1.onClick(MqttSample.java:38)
android.view.View.performClick(View.java:4202)
android.view.View$PerformClick.run(View.java:17340)
android.os.Handler.handleCallback(Handler.java:725)
android.os.Handler.dispatchMessage(Handler.java:92)
android.os.Looper.loop(Looper.java:137)
android.app.ActivityThread.main(ActivityThread.java:5039)
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke(Method.java:511)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
dalvik.system.NativeStart.main(Native Method)    

person Thor69    schedule 21.11.2012    source источник
comment
Я только что проверил это же приложение на реальном смартфоне (Samsung Mini 2) с тем же результатом.   -  person Thor69    schedule 22.11.2012


Ответы (5)


В качестве альтернативы вы можете использовать экземпляр класса MemoryPersistence, если вы не полагаетесь на сохраняемость файлов.

Таким образом, вызов для получения клиента будет выглядеть так:

MemoryPersistence persistence = new MemoryPersistence();
MqttClient client = new MqttClient(host, clientId, persistence);
person f_8    schedule 23.11.2012
comment
Спасибо. Я знал о возможности использования внутренней памяти, но я только приближаюсь к MQTT, и я хотел бы знать, где была проблема с сохранением файлов. - person Thor69; 23.11.2012

После целого дня, потраченного на понимание проблемы и поиски ее в любом месте, в конце концов я понял: очень просто нужно добавить разрешение в манифест.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Я не знаю, можно ли использовать внутренние каталоги вместо SD-карты.

Поскольку я впервые отвечаю на свой вопрос, дайте мне знать, является ли хорошим тоном помечать свой ответ как правильный (я нашел разные мнения по этим темам)

person Thor69    schedule 23.11.2012

Это решило мою проблему.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Вокруг WAMP также есть немного насмешек.

person Raghulan Gowthaman    schedule 17.04.2014

Ошибка связана с тем, что клиентский код MQTT пытается открыть файл в локальном хранилище для хранения сообщений при публикации с высоким (1/2) уровнем QOS. Будет 2 причины ошибки:

1. Возможно, вы не предоставили приложению доступ к хранилищу.

2. Маловероятно, что у вас есть разрешение на запись в расположение по умолчанию, которое выбирает клиент MQTT.

Самый простой способ обойти это — использовать хранилище в памяти (org.eclipse.paho.client.mqttv3.persist.MemoryPersistence) для клиента MQTT.

...
MemoryPersistence persistence = new MemoryPersistence();
client = new MqttClient("tcp://test.mosquitto.org:1883", clientId);
...

Как только вы справитесь с этой проблемой, вы, вероятно, столкнетесь с проблемой выполнения сетевого ввода-вывода в потоке пользовательского интерфейса. Чтобы избежать этого, я предлагаю вам посмотреть код AsyncTask, который предоставляет Android.

person Piyush Mittal    schedule 26.08.2017
comment
Расположение по умолчанию, которое использует класс MqttDefaultFilePersistence, — System.getProperty(user.dir). В моем экземпляре OpenShift это вернуло корневой каталог /, что меня действительно смутило, потому что нет возможности записать в корневой каталог в средах Linux, я думаю, поэтому команда открытия файла все равно не работает. - person mwalter; 28.09.2017

person    schedule
comment
Дампы кода без объяснения причин редко бывают полезными. Пожалуйста, рассмотрите возможность добавления некоторого контекста к вашему ответу. - person Chris; 07.11.2014
comment
Как сказал Крис, вам действительно нужно объяснить, что вы имеете в виду. Тем более, если вы отвечаете на старый вопрос, на который есть принятый ответ, вы должны объяснить, почему ваш ответ лучше. - person hardillb; 07.11.2014
comment
Какое объяснение вам нужно? Он создал внутреннюю персистентную переменную и передал ее методу, вот и все. Я применил его, больше нет ошибки разрешения на сохранение, спасибо! Для неудовлетворенных, неблагодарных и токсичных комментаторов, у которых, вероятно, даже не было этой проблемы, но, тем не менее, они пришли сюда, чтобы проголосовать и пожаловаться - позор вам. В следующий раз, прежде чем плакать, попробуйте его решение, не ждите, что все будут кормить вас с ложечки, особенно бесплатно. - person zemaitis; 18.05.2018
comment
Я согласен с @zemaitis. Все самоочевидно и работает как шарм для меня. Такое количество минусов без причины абсолютно не нужно, он просто помог тому, кто просит. +1 за тебя, чувак, спасибо! - person Antonio Vlasic; 12.09.2018
comment
Рецензенты должны понимать, что stackoverflow — это не наша работа на полную ставку, и мы делимся ею, когда у нас есть время. Если у нас нет времени, мы, по крайней мере, укажем вам правильное направление. - person zemaitis; 12.09.2018