Android Studio使用RabbitMQ

本指南介绍了如何 使用Android Studio和 RabbitMQ Android中 创建简单的聊天应用程序 每个拥有该应用程序的人都能够发送和接收来自使用相同应用程序的所有其他用户的消息。

如果您使用的是Eclipse,请查看 此博客文章 。

在给定的代码中,消息将首先被添加到内部队列,发布者将在建立连接时从内部队列发送消息到RabbitMQ。如果连接断开,消息将被添加回队列。

RabbitMQ Android

本指南假定您已经下载,安装并设置了适用于Android Studio的所有内容 

首先创建一个新的Android项目,打开Android Studio,然后进入文件 - >新建 - >新建项目。

1.配置你的新项目

  1. 输入以下指定的项目信息。

    创建新的android项目

  2. 选择您的应用程序将运行的形状因子

    android工作室

  3. 选择是否要将活动添加到您的应用程序。在这个例子中,我们选择 Blank Activity 来为项目获取自动生成的文件。

    添加android活动

  4. 自定义活动

    自定义android活动

2.将Java AMQP库添加到项目中

RabbitMQ开发了一个优秀的 Java AMQP库该库的完整API文档可以在这里找到 

我们需要包含RabbitMQ Java客户端库并将jar文件引用到项目中。在Android Studio中,您可以在与应用程序相同的级别创建一个libs文件夹。复制并放置在这个libs文件夹中。标记所有的jar文件,并按下 “添加为库...” ,如下图所示。

添加rabbitmq库

你可以通过打开build.gradle来确认libs已经被添加为库了, 并且在依赖关系下检查  所有的文件都应该在那里。

dependencies {
                  ...
                  compile files('libs/rabbitmq-client.jar')
                  ...
                }

注意:只有当您使用Android Gradle插件0.7.0并在稍后运行应用程序时发生错误“APK中复制的文件复制”时,您需要将packagingOptions添加到您的build.gradle文件中,如此 处所述。

android {
                  packagingOptions {
                    exclude 'META-INF/LICENSE.txt'
                    exclude 'META-INF/NOTICE.txt'
                  }
                }

3. Android Manifest,互联网许可

我们需要告诉Android系统,这个应用程序被允许访问互联网。打开位于项目根目录下的AndroidManifest.xml文件。在关闭/清单标签之前添加用户权限android.permission.INTERNET。

<?xml version="1.0" encoding="utf-8"?>
                <manifest xmlns:android="http://schemas.android.com/apk/res/android"
                      package="com.cloudamqp.rabbitmq"
                     android:versionCode="1"
                     android:versionName="1.0">
                     ......
                     <uses-permission android:name="android.permission.INTERNET"></uses-permission>
                </manifest>

4.开始编码

布局

为应用程序创建视图。.xml布局文件可以在res-> layout下找到。我们这里有一个根ScrollView包含一个

EditText  a  Button  和a  TextView  EditText将被用作将要发送的文本的输入字段。文本将在按下按钮时发布,订阅者收到的所有消息都将被打印到TextView。
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
                  ...
                  <EditText
                  android:id="@+id/text"
                  android:layout_width="fill_parent"
                  android:background="#ffffff"
                  android:hint="Enter a message" />
                
                  <Button
                  android:id="@+id/publish"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:layout_below="@+id/text"
                  android:text="Publish message" />
                
                  <TextView
                  android:id="@+id/textView"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:layout_below="@+id/publish"
                  android:textColor="#000000" />
                  ...
                </ScrollView>

发布

创建一个内部消息队列。在这种情况下是一个 BlockingDeque 使用。 Blockingqueues 实现被设计为主要用于生产者 - 消费者队列。

private BlockingDeque<String> queue = new LinkedBlockingDeque>String>();
void publishMessage(String message) {
  try {
    Log.d("","[q] " + message);
    queue.putLast(message);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
}

ConnectionFactory 连接工厂创建一个设置函数 封装一组连接配置参数,在本例中为CLOUDAMQP_URL。该URL可以在您的实例的控制面板中找到。

ConnectionFactory factory = new ConnectionFactory();
private void setupConnectionFactory() {
  String uri = "CLOUDAMQP_URL";
  try {
    factory.setAutomaticRecoveryEnabled(false);
    factory.setUri(uri);
  } catch (KeyManagementException | NoSuchAlgorithmException | URISyntaxException e1) {
    e1.printStackTrace();
}

创建从内部队列发布消息的发布者。如果发现异常,则将消息添加回队列。如果连接中断,发布者将尝试每5秒重新连接一次。

当我们执行不是即时的操作(比如连接到rabbitMQ的网络访问)时,需要线程(“后台”或“工作者”线程或使用AsyncTask类)。

我们将使用扇出交换。扇出交换将消息路由到与其绑定的所有队列,并且路由密钥被忽略。如果N个队列被绑定到扇出交换机,那么将被发布到该交换机的新消息复制并传送到所有N个队列。扇出交换是消息广播路由的理想选择。

public void publishToAMQP()
{
  publishThread = new Thread(new Runnable() {
    @Override
    public void run() {
      while(true) {
        try {
          Connection connection = factory.newConnection();
          Channel ch = connection.createChannel();
          ch.confirmSelect();

          while (true) {
            String message = queue.takeFirst();
            try{
              ch.basicPublish("amq.fanout", "chat", null, message.getBytes());
              Log.d("", "[s] " + message);
              ch.waitForConfirmsOrDie();
            } catch (Exception e){
              Log.d("","[f] " + message);
              queue.putFirst(message);
              throw e;
           }
         }
       } catch (InterruptedException e) {
         break;
       } catch (Exception e) {
         Log.d("", "Connection broken: " + e.getClass().getName());
         try {
           Thread.sleep(5000); //sleep and then try again
         } catch (InterruptedException e1) {
           break;
         }
       }
     }
   }
  });
  publishThread.start();
}

订户

我们现在已经创建了发布者,现在是创建订阅者的时候了。订户将采取一个处理程序作为参数。消息到达时,处理程序将把消息打印到屏幕上。当连接中断时,订阅线程将尝试每5秒重新连接一次。

void subscribe(final Handler handler)
              {
                subscribeThread = new Thread(new Runnable() {
                  @Override
                  public void run() {
                    while(true) {
                      try {
                        Connection connection = factory.newConnection();
                        Channel channel = connection.createChannel();
                        channel.basicQos(1);
                        DeclareOk q = channel.queueDeclare();
                        channel.queueBind(q.getQueue(), "amq.fanout", "chat");
                        QueueingConsumer consumer = new QueueingConsumer(channel);
                        channel.basicConsume(q.getQueue(), true, consumer);
              
                        while (true) {
                          QueueingConsumer.Delivery delivery = consumer.nextDelivery();
                          String message = new String(delivery.getBody());
                          Log.d("","[r] " + message);
                          Message msg = handler.obtainMessage();
                          Bundle bundle = new Bundle();
                          bundle.putString("msg", message);
                          msg.setData(bundle);
                          handler.sendMessage(msg);
                        }
                      } catch (InterruptedException e) {
                        break;
                      } catch (Exception e1) {
                        Log.d("", "Connection broken: " + e1.getClass().getName());
                        try {
                          Thread.sleep(5000); //sleep and then try again
                        } catch (InterruptedException e) {
                          break;
                        }
                      }
                    }
                  }
                });
                subscribeThread.start();
              }

从函数调用上面列出的所有函数 onCreate 订阅函数使用的处理程序也是在onCreate中创建的。必须使用处理程序,因为只能从主要写入到GUI。

@Override
              public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
              
                setupConnectionFactory();
                publishToAMQP();
                setupPubButton();
              
                final Handler incomingMessageHandler = new Handler() {
                  @Override
                  public void handleMessage(Message msg) {
                    String message = msg.getData().getString("msg");
                    TextView tv = (TextView) findViewById(R.id.textView);
                    Date now = new Date();
                    SimpleDateFormat ft = new SimpleDateFormat ("hh:mm:ss");
                    tv.append(ft.format(now) + ' ' + message + '\n');
                  }
                };
                subscribe(incomingMessageHandler);
              }
              
              void setupPubButton() {
                Button button = (Button) findViewById(R.id.publish);
                button.setOnClickListener(new OnClickListener() {
                  @Override
                  public void onClick(View arg0) {
                    EditText et = (EditText) findViewById(R.id.text);
                    publishMessage(et.getText().toString());
                    et.setText("");
                 }
                });
              }

当应用程序被添加下面的代码销毁时,订阅和发布步骤都可以被中断 onDestroy

Thread subscribeThread;
              Thread publishThread;
              @Override
              protected void onDestroy() {
                super.onDestroy();
                publishThread.interrupt();
                subscribeThread.interrupt();
              }

完整的代码可以从github,github.com/cloudamqp/android-example中看到并下载

https://www.cloudamqp.com/blog/2015-07-29-rabbitmq-on-android.html 


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android可以使用RabbitMQ来实现消息队列的功能。RabbitMQ是一种开源的消息代理,它可以在分布式系统中进行消息的传递和处理。 要在Android使用RabbitMQ,需要进行以下步骤: 1. 添加RabbitMQ的依赖库:在项目的build.gradle文件中添加以下代码: ``` dependencies { implementation 'com.rabbitmq:amqp-client:5.12.0' } ``` 2. 创建RabbitMQ连接:在Android应用中通过AMQP协议与RabbitMQ服务进行通信,需要使用RabbitMQ的Java客户端。在连接前需要先创建一个ConnectionFactory对象: ``` ConnectionFactory factory = new ConnectionFactory(); factory.setHost("your-rabbitmq-hostname"); factory.setUsername("your-rabbitmq-username"); factory.setPassword("your-rabbitmq-password"); ``` 3. 创建通道和队列:通过连接创建一个通道,然后使用通道创建一个队列: ``` Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.queueDeclare("your-queue-name", false, false, false, null); ``` 4. 发送消息:通过通道将消息发送到队列中: ``` String message = "Hello, RabbitMQ!"; channel.basicPublish("", "your-queue-name", null, message.getBytes("UTF-8")); ``` 5. 接收消息:通过监听队列获取消息: ``` Consumer consumer = new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { String message = new String(body, "UTF-8"); Log.d(TAG, "Received message: " + message); } }; channel.basicConsume("your-queue-name", true, consumer); ``` 注意,在使用RabbitMQ时需要考虑到网络连接和消息传递的安全性。另外,在使用完连接和通道后,需要关闭它们以释放资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值