在学习 Java/Android 开发的过程中,我遇到了很多障碍。主要是因为我对线程和线程/进程之间的通信了解不多。我正在尝试将 IMU 数据从 Android 设备传输到计算机上的 Python 应用程序。每当传感器值发生变化时,传感器监听器都会将当前值保存到一个变量中,供网络处理程序访问。
网络处理程序反过来应该在计时器上运行,以或多或少的 33Hz 固定速率发送值和当前时间戳(也许有点快?好吧,我愿意接受慢到10Hz,但不会比这慢)。无论如何,当我测试这个时,我可以在计算机界面上看到数据几乎不是以每秒 30 个的稳定速度进入,而是涌入,有时一秒钟都没有,并且总体上在累积相当延迟(即值越晚,它们进入的延迟越多)。我知道网络中可能存在一些变化和一些滞后,但我至少希望整体速度至少是正确的,即我发送的时间不会越长越糟。
考虑到这些设备都在一个普通的 wifi 网络上,并且我能够流式传输 1080p 视频而不会在 wifi 上有任何延迟,我相当有信心该协议(protocol)应该能够每 30 毫秒处理一个 64 字节的字符串而不会出现问题.为了消除传感器读取器作为问题来源,我做了一个最小的工作示例,它只是每 30 毫秒发送一个字符串,没有任何传感器读取。我基本上是从各种 stackoverflow 帖子中获取这段代码,并对其进行修改,直到它或多或少地完成了我想要的。问题是网络接口(interface)在 AsynchronousTask 中运行,我不确定一旦它启动后如何访问它。我的理论是,为每个新数据包打开一个新套接字是在浪费资源,但我不确定如何在后台打开一次套接字,然后在计时器上将值传递给它并告诉它发送。
这是我为测试这个所做的基本 Activity :
package com.jamesdoesntlikejava.motionlearning15;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import java.util.Timer;
import java.util.TimerTask;
public class SendValuesActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_send_values);
// creating timer task, timer
final Timer timer = new Timer();
TimerTask taskNew = new TimerTask() {
@Override
public void run() {
int counter = 0;
int numsteps = 333;
String params[] = new String[2];
if (counter < numsteps) {
params[0] = "192.168.1.33";
long currentTime = System.currentTimeMillis();
params[1] = Long.toString(currentTime)+"blablabla";
new ServerCommunicationTask().execute(params);
counter++;
} else {
timer.cancel();
timer.purge();
}
}
};
// scheduling the task at fixed rate delay
Toast.makeText(this, "Sending Values in 1s...", Toast.LENGTH_SHORT).show();
timer.scheduleAtFixedRate(taskNew,1000,30);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_send_values, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
这是做网络的类:
package com.jamesdoesntlikejava.motionlearning15;
import android.os.AsyncTask;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class ServerCommunicationTask extends AsyncTask<String, Void, String> {
public final static int TCP_SERVER_PORT = 13337;
// params are 0: the target IP and 1: the message to send.
@Override
protected String doInBackground(String[] params) {
String TCP_SERVER_IP = params[0];
try {
Socket s = new Socket(TCP_SERVER_IP, TCP_SERVER_PORT);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//send output msg
String outMsg = params[1];
out.write(outMsg);
out.flush();
//close connection
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "success";
}
@Override
protected void onPostExecute(String response) {
}
}
在装有 android 5.1 的 Moto G LTE(更新的第一代)上运行。感谢任何提示,谢谢!
最佳答案
您可以使用 Thread,而不是 AsyncTask 和总是打开新连接。
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
public class ServerCommunicationThread extends Thread {
public final static int TCP_SERVER_PORT = 13337;
private ArrayList<String> mMessages = new ArrayList<>();
private String mServer;
private boolean mRun = true;
public ServerCommunicationThread(String server) {
this.mServer = server;
}
@Override
public void run() {
while (mRun) {
Socket s = null;
try {
s = new Socket(mServer, TCP_SERVER_PORT);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
while (mRun) {
String message;
// Wait for message
synchronized (mMessages) {
while (mMessages.isEmpty()) {
try {
mMessages.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// Get message and remove from the list
message = mMessages.get(0);
mMessages.remove(0);
}
//send output msg
String outMsg = message;
out.write(outMsg);
out.flush();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//close connection
if (s != null) {
try {
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public void send(String message) {
synchronized (mMessages) {
mMessages.add(message);
mMessages.notify();
}
}
public void close() {
mRun = false;
}
}
您可以在连接打开的情况下保持线程运行,并在需要时发送消息。
ServerCommunicationThread thread = new ServerCommunicationThread("192.168.1.33");
thread.start();
...
thread.send("blablabla");
...
thread.send("blablabla");
...
thread.close();
请注意,此代码未经测试。
关于java - 通过 TCP/IP 从 Droid 发送恒定速率数据流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34374050/
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
我正在使用puppet为ruby程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题: