我有一个在Android设备(手机/平板电脑)上运行的Android应用程序。 我想在设备和笔记本电脑附近创建一个连接,以便将一些数据从Android应用程序发送到笔记本电脑上运行的Java应用程序。
根据您的经验,实现该连接的最佳/最简单方法是什么? 我应该连接套接字吗?串口连接?蓝牙连接?也许无线? 我认为套接字连接是我对这个特定项目最不喜欢的。
我应该说我以前没有尝试过任何关于android的连接类型。
有什么建议吗?我愿意接受建议 谢谢。
答案 0 :(得分:0)
您可以尝试通过Wifi使用套接字!我设法使它工作,这很容易:)
以下是打开套接字并读取数据的AsyncTask示例
class WifiDataAsyncTask extends AsyncTask<Integer, Void, Void> {
private final String TAG = this.getClass().getName();
private Socket sock;
private Context context;
private WifiManager wifiManager;
private BufferedReader br;
WifiDataAsyncTask(Context context, WifiManager wifiManager) {
this.context = context;
this.wifiManager = wifiManager;
}
@Override
protected Void doInBackground(Integer... numPort) {
int rawChar;
sock = new Socket();
try {
Log.d(TAG, "Creating socket on IP " + getIpAddress(wifiManager) + ":" + numPort[0]);
sock.setReuseAddress(true);
}
catch (IOException e) {
Log.d(TAG, "Error set reuseaddress");
e.printStackTrace();
}
try {
sock.connect(new InetSocketAddress(getIpAddress(wifiManager), numPort[0]));
} catch (IOException ex) {
Log.d(TAG, "Error connection socket");
ex.printStackTrace();
}
if (sock.isConnected()) {
try {
br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
StringBuilder toSave = new StringBuilder();
// -1 : end of the stream
// isCancelled() tells you if the asynctask has been cancelled in the Main Activity
while ((rawChar = br.read()) != -1 && !isCancelled()) {
char c = (char) rawChar;
if (c == '\0') {
// Add the char to the string to save
toSave.append('\n');
// DO STUFF WITH YOUR STRING DATA
toSave.setLength(0);
} else {
toSave.append(c);
}
}
} catch (IOException ex) {
Log.d(TAG, "Error read InputStream:");
ex.printStackTrace();
}
try {
closeConnection();
} catch (IOException e) {
Log.d(TAG, "Error close connection:");
e.printStackTrace();
}
}
return null;
}
private void closeConnection() throws IOException {
// If InputStream Closed (Wifi disconnected or server stopped)
try {
if (br != null) {
br.close();
}
} finally {
sock.close();
Log.d(TAG, "Socket closed");
// Tell Main Activity that the socket has closed
Intent intent = new Intent(context.getResources().getString(R.string.CloseSocketAction));
context.sendBroadcast(intent);
}
}
private String getIpAddress(WifiManager wifiManager) {
DhcpInfo dhcpInfo = wifiManager.getDhcpInfo();
byte[] ipAddress = convert2Bytes(dhcpInfo.serverAddress);
try {
return InetAddress.getByAddress(ipAddress).getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
return null;
}
private byte[] convert2Bytes(int hostAddress) {
return new byte[]{(byte) (0xff & hostAddress),
(byte) (0xff & (hostAddress >> 8)),
(byte) (0xff & (hostAddress >> 16)),
(byte) (0xff & (hostAddress >> 24))};
}
}
主要活动可以是这样的:
public class TestFragment extends Fragment {
private final String TAG = this.getClass().getName();
private View mLayout;
private WifiManager wifiManager;
private WifiDataAsyncTask wifiDataAsyncTask;
private CloseSocketReceiver closeSocketReceiver;
class CloseSocketReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(getResources().getString(R.string.CloseSocketAction))) {
Log.d(TAG, "CloseSocketReceiver");
}
}
}
private void startWifiDataAsyncTask() {
// Create AsyncTasks
wifiDataAsyncTask = new WifiDataAsyncTask(getContext(), wifiManager);
wifiDataAsyncTask.execute(getResources().getInteger(R.integer.NUMPORT));
}
private void stopWifiDataAsyncTask() {
wifiDataAsyncTask.cancel(true);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_osselet, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mLayout = view;
wifiManager = (WifiManager) getActivity().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
// Create receiver
closeSocketReceiver = new CloseSocketReceiver();
}
@Override
public void onStart() {
super.onStart();
getActivity().registerReceiver(closeSocketReceiver, new IntentFilter(getResources().getString(R.string.CloseSocketAction)));
}
public void onStop() {
super.onStop();
getActivity().unregisterReceiver(closeSocketReceiver);
}
}
在清单中,添加互联网权限以使用Wifi:
<uses-permission android:name="android.permission.INTERNET" />
这是发送String消息的C ++ Server.cpp:
#include <errno.h>
#include<stdio.h>
#include<stdlib.h>
#include <strings.h>
#include <string.h>
#include "Server.h"
#include "common.h"
#include <unistd.h>
#include <sys/ioctl.h>
using namespace std;
Server::Server(int num_port) {
this->num_port = num_port;
}
void Server::init() { // Init socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
fprintf(stderr, "Error opening socket\n");
}
// Allow to reuse socket immediately after closing server
int enabled = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enabled, sizeof(int)) < 0) {
fprintf(stderr, "setsockopt(SO_REUSEADDR) failed\n");
}
printf("Server Socket created on port %d\n", num_port);
// Init server_addr
bzero((char*) &server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(num_port);
// Init newsockfd
newsockfd = -1;
}
Server::~Server() {
close(sockfd);
close(newsockfd);
}
void Server::bind() {
// Binding socket
if(::bind(sockfd, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0){
fprintf(stderr, "Error Binding Socket\n");
exit(1);
}
}
void Server::listen(int maxClient) {
printf("Look up for clients on port %d\n", num_port);
// Define number of max clients
::listen(sockfd, maxClient);
}
int Server::start() {
struct sockaddr_in cli_addr;
socklen_t clilen = sizeof(cli_addr);
fd_set set;
struct timeval timeout;
int rv;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
newsockfd = -1;
// Check if newsockfd assigned or Ctrl-C handled
while (newsockfd == -1 && signaled == 0) {
// Reset into the loop
// After listen returns, set have been updated and
// starting another select will not wait on
// the updated file descriptors
// After first call, no client here, set updated and not
// listen anymore -> need to reset
FD_ZERO(&set); /* Clear set */
FD_SET(sockfd, &set); /* Add file descriptor to the set */
rv = select(sockfd + 1, &set, NULL, NULL, &timeout);
if (rv == -1) {
fprintf(stderr, "Error select\n");
exit(1);
}
else if (rv == 0) {
//fprintf(stderr, "Timeout occurred\n");
}
else {
// Accept client
newsockfd = accept(sockfd, (struct sockaddr*) &cli_addr, &clilen);
if(newsockfd < 0){
fprintf(stderr, "Error Client not accepted by server\n");
}
// Set timeout to write
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 10;
if (setsockopt (newsockfd, SOL_SOCKET, SO_SNDTIMEO, (char *) &timeout, sizeof(timeout)) < 0) {
fprintf(stderr, "setsockopt(SO_SNDTIMEO) failed\n");
}
printf("Client accepted on port %d\n", num_port);
}
}
printf("Server.start() terminated\n");
return newsockfd;
}
int Server::sendData(char* toSend, int size) {
// Check is socket closed
int n = write(newsockfd, toSend, size);
if (n < 0) {
fprintf(stderr, "Error sending message\n");
}
else {
//printf("Message %s sent to the client on port %d\n", toSend, num_port);
}
return n;
}
void Server::closeClientSocket() {
close(newsockfd);
}
void Server::stop() {
printf("Closing sockets\n");
close(newsockfd);
close(sockfd);
}
最后是Server.h
#ifndef SERVER_H
#define SERVER_H
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
class Server {
private:
int num_port;
int sockfd, newsockfd;
struct sockaddr_in server_addr;
public:
Server(int num_port); // Constructor
~Server(); // Desctructor
void init();
void allowReuse();
void bind();
void listen(int);
int start();
int sendData(char*, int);
void closeClientSocket();
void stop();
};
#endif
希望它有所帮助!
答案 1 :(得分:0)
此示例使用RX
显示<强> MainActivity.java 强>
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStartRX = TrafficStats.getTotalRxBytes();
mStartTX = TrafficStats.getTotalTxBytes();
if (mStartRX == TrafficStats.UNSUPPORTED || mStartTX == TrafficStats.UNSUPPORTED) {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Uh Oh!");
alert.setMessage("Your device does not support traffic stat monitoring.");
alert.show();
} else {
mHandler.postDelayed(mRunnable, 1000);
}
}
我们需要更新我们的显示并重新安排runnable:
private final Runnable mRunnable = new Runnable() {
public void run() {
TextView RX = (TextView) findViewById(R.id.RX);
TextView TX = (TextView) findViewById(R.id.TX);
long rxBytes = TrafficStats.getTotalRxBytes() - mStartRX;
RX.setText(Long.toString(rxBytes));
long txBytes = TrafficStats.getTotalTxBytes() - mStartTX;
TX.setText(Long.toString(txBytes));
mHandler.postDelayed(mRunnable, 1000);
}
};