【问题标题】:again: Android MQTT unable to create client再次:Android MQTT 无法创建客户端
【发布时间】:2012-11-09 20:47:44
【问题描述】:

我正在尝试在 Android 中创建一个 MqttClient,使用 ADT 上的 Android 模拟器 (Nexus7)(Linux Fedora17 上的 Eclipse 3.8.0。 我发现这个问题回答了(Android MQTT unable to create client),但它未能解决我的问题。

我创建了一个活动,允许用户进入存储 presistence 文件的目录,但无法避免捕获异常。 我尝试了“/mnt/sdcard/”、“/mnt/”、“/mnt/sdcard/tmp/”和类似的。

我需要注意 Eclipse 项目中 Android 模拟器中的特定设置吗? 应用程序中是否包含任何使用权限?

我查看了引用的已回答问题中提到的各种 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)    

【问题讨论】:

  • 我刚刚在真正的智能手机(Samsung Mini 2)上测试了相同的应用程序,结果相同。

标签: android adt mqtt


【解决方案1】:

花了一整天的时间了解问题并在任何地方搜索它,最终我明白了:非常简单地,必须将权限添加到清单中

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

不知道能不能用内部目录代替sdcard。

由于这是我第一次回答我自己的问题,请让我知道将我自己的答案标记为正确答案是否是一种好的礼仪(我在这个话题上发现了不同的意见)

【讨论】:

    【解决方案2】:

    如果您不依赖文件持久性,您也可以使用 MemoryPersistence 类的实例。

    所以获取客户的电话是:

    MemoryPersistence persistence = new MemoryPersistence();
    MqttClient client = new MqttClient(host, clientId, persistence);
    

    【讨论】:

    • 谢谢。我知道使用内部存储器的可能性,但我刚刚接近 MQTT,我想知道文件持久性的问题出在哪里。
    【解决方案3】:

    这解决了我的问题。

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

    WAMP 周围也有一些嘲笑。

    【讨论】:

      【解决方案4】:
              MqttClientPersistence persistence = new MqttDefaultFilePersistence(mContext.getApplicationInfo().dataDir);
              mqttclient = new MqttAsyncClient(url.toString(), clientId, persistence);
      

      【讨论】:

      • 没有解释的代码转储很少有用。请考虑在您的答案中添加一些上下文。
      • 正如克里斯所说,你真的需要解释你的意思。更重要的是,如果回答一个已被接受的旧问题,您应该解释为什么您的答案更好。
      • 你需要什么解释?他创建了内部持久性变量并将其传递给方法,就是这样。我申请了,没有持久化权限错误,谢谢!对于不满意、忘恩负义和有毒的评论者,他们可能甚至没有这个问题,但无论如何都来这里投反对票和抱怨——真丢脸。下次在哭之前尝试他的解决方案,不要指望每个人都用勺子喂你,尤其是免费的。
      • 我同意@zemaitis。一切都是不言自明的,对我来说就像一种魅力。这种无缘无故的反对票绝对不需要,他只是帮助了提问的人。为你+1,谢谢!
      • 审稿人需要明白,stackoverflow 不是我们的全职工作,我们会在有空的时候分享。如果我们没有时间,我们至少会为您指明正确的方向。
      【解决方案5】:

      该错误是因为 MQTT 客户端代码在以高 (1/2) QOS 级别发布时试图打开本地存储上的文件以存储消息。错误的原因有两个:

      1.您可能没有授予应用程序的存储访问权限

      2.您不太可能拥有写入 MQTT 客户端选择的默认位置的权限。

      解决此问题的最简单方法是为 MQTT 客户端使用内存存储 (org.eclipse.paho.client.mqttv3.persist.MemoryPersistence)。

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

      一旦你解决了这个问题,你很可能会遇到在 UI 线程上执行网络 io 的问题。为避免这种情况,我建议您查看 Android 提供的 AsyncTask 代码

      【讨论】:

      • 类 MqttDefaultFilePersistence 使用的默认位置是 System.getProperty("user.dir")。在我的 OpenShift 实例上,这返回了根目录“/”,这让我很困惑,因为我认为在 Linux 环境中无法写入根目录,因此打开文件命令无论如何都会失败。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-12
      • 2016-10-27
      • 2013-10-06
      • 2018-01-05
      • 2014-12-12
      • 1970-01-01
      相关资源
      最近更新 更多