8

I'm trying to create an MqttClient in Android, using an Android emulator (Nexus7) on ADT (Eclipse 3.8.0 on a Linux Fedora17. I found this question answered (Android MQTT unable to create client), but it failed to solve my problem.

I created an activity that allows the user to enter the directory where to store the presistence file, but there is no way to avoid catching the exception. I tried with "/mnt/sdcard/", "/mnt/", "/mnt/sdcard/tmp/" and similar.

Do I need to pay attention to particular settings in Android emulator on in Eclipse project? Are there any uses-permissions to be included in the application?

I looked at the various mqtt resources mentioned in the quoted answered question, but I couldn't manage to find an answer.

This is my code:

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;
    }

}

and this is the Stack:

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)    
4

5 回答 5

10

You could alternatively use an instance of the class MemoryPersistence if you don't rely on file persistency.

So the call to get a client would be:

MemoryPersistence persistence = new MemoryPersistence();
MqttClient client = new MqttClient(host, clientId, persistence);
于 2012-11-23T10:53:24.430 回答
6

After a whole day spent in understanding the issue and in googling anywhere to find it, eventually I got it: very simply a permission has to be added to the manifest

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

I don't know whether internal directories can be used instead of the sdcard.

As this is the first time I answer my own question, let me know whether it is a good etiquette to flag as correct answer my own answer (I found different opinions on this topics)

于 2012-11-23T09:12:47.243 回答
0

This solved my issue.

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

There is a bit mocking around the WAMP as well.

于 2014-04-17T02:37:33.953 回答
0
        MqttClientPersistence persistence = new MqttDefaultFilePersistence(mContext.getApplicationInfo().dataDir);
        mqttclient = new MqttAsyncClient(url.toString(), clientId, persistence);
于 2014-11-07T18:07:10.937 回答
0

The error is because the MQTT client code is trying to open a file on the local storage to store messages in when publishing at high (1/2) QOS levels. There will be 2 causes for the error:

1.You may not have granted storage access to the application

2.You are unlikely to have permission to write to the default location that the MQTT client chooses.

The easiest way to get round this is to use the in memory storage (org.eclipse.paho.client.mqttv3.persist.MemoryPersistence) for the MQTT client.

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

Once you get round that problem you are likely to run into the issue of doing network io on the UI thread. To avoid that I suggest you look at the AsyncTask code that Android provides

于 2017-08-26T19:35:02.890 回答