I have a Nexus 5X that is having intermittent receive problems. I have been able to run the code on an Asus tablet, two Samsung tablets, and a Kindle Fire with no issues. The code is based on this repository:
https://github.com/moonlight-stream/moonlight-common/blob/master/src/com/limelight/nvstream/av/video/VideoStream.java
Here is the pertinent code:
WifiManager wifiMgr = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifiLock = wifiMgr.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "Player");
wifiLock.setReferenceCounted(false);
wifiLock.acquire();
rtp = new DatagramSocket(RTP_PORT);
rtp.setReceiveBufferSize(256*1024);
// Receive thread
Thread t = new Thread() {
#Override
public void run() {
while (!isInterrupted())
{
try {
// Pull the next buffer in the ring and reset it
buffer = ring[ringIndex].getBuffer();
// Read the video data off the network
packet.setData(buffer, 0, buffer.length);
rtp.receive(packet);
// Do processing here
} catch (IOException e) {
return;
}
}
}
};
threads.add(t);
t.setName("Video - Receive");
t.setPriority(Thread.MAX_PRIORITY - 1);
t.start();
I am as sure as I can be that the UDP stream is properly being sent to the device. Most of the packets are received correctly. However, I've noticed in a method trace that the
rtp.receive(packet);
can block for 100s-1000s of milliseconds. When running on a different device in the exact same architecture, I see essentially 100% packet success and a maximum block of maybe 60ms.
I have tried this on 2.4G, and 5G, on multiple routers. The problem follows the device.
The packets being sent are UDP directly to the device. There are no IP conflicts on the network.
Any thoughts on what might be going wrong? Thank you very much!
EDIT: I should note the CPU usage is around 2%, and the memory usage is around 10MB
EDIT 2: I created a bare application to simply investigate this issue. I see the same results. I'll see 30,000+ consecutive packets on several devices without a single drop. I'll drop a range of packets every couple seconds on a Nexus 5X. I've had someone remotely run this test application on their Nexus 5X, and they reported that no packets were dropped. All signs are pointing to a driver / radio issue as far as I know...
package com.udp_receiver_test;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.nio.ByteBuffer;
public class MainActivity extends AppCompatActivity {
private WifiManager.WifiLock wifiLock;
Thread t;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "Player");
wifiLock.setReferenceCounted(false);
wifiLock.acquire();
// Use sustained performance mode on N+ to ensure consistent
// CPU availability
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
getWindow().setSustainedPerformanceMode(true);
}
startListenThread();
}
private void startListenThread()
{
t = new Thread() {
#Override
public void run()
{
DatagramSocket socket;
int nextSequenceNumber = 0;
ByteBuffer byteBuffer;
int BufferSize = 1292;
int NumRingElements = 784;
long correctPacketCounter = 0;
byte ring[][] = new byte[NumRingElements][1292];
try {
socket = new DatagramSocket(12345);
socket.setReceiveBufferSize(256 * 1024);
} catch (Exception e) {
e.printStackTrace();
return;
}
byte[] buffer;
int ringCounter = 0;
DatagramPacket packet = new DatagramPacket(new byte[1], 1);
//short rtpSequenceNumber;
int sequenceNumber;
while (!isInterrupted()) {
try {
buffer = ring[ringCounter];
packet.setData(buffer, 0, buffer.length);
socket.receive(packet);
if (packet.getLength() > 20) {
// Read the RTP sequence number field (big endian)
byteBuffer = ByteBuffer.wrap(buffer);
byteBuffer.position(16);
sequenceNumber = (byteBuffer.getInt() >> 8) & 0xFFFFFF;
if (sequenceNumber != nextSequenceNumber) {
Log.d("TAG", "Not next sequence number - Got:" + sequenceNumber + " Expected:" + nextSequenceNumber);
} else {
if (((++correctPacketCounter) % 100) == 0)
{
Log.d("TAG", "Correct packets = " + correctPacketCounter);
}
}
nextSequenceNumber = (sequenceNumber + 256) % 65535;
} else {
Log.d("TAG", "Message too short");
}
ringCounter = (ringCounter + 1) % NumRingElements;
} catch (Exception e) {
e.printStackTrace();
return;
}
}
}
};
t.setName("Receiver");
t.setPriority(Thread.MAX_PRIORITY - 1);
t.start();
}
#Override
public void onStop()
{
super.onStop();
wifiLock.release();
if (t.isAlive()) {
t.interrupt();
}
}
}
Related
I am working on a project which requires to send Audio frames from client to server whenever the speech is detected. The client is android app and the server is a simple python script. I am using socket to transfer my data between them. The whole project works well except the audio quality. The Audio received is a fast from the audio sent. If i send 30 sec audio from the client only 20 sec audio is received. Later on i added a simple line to check the sent and received byte length and i could notice a lot of frames missing on the receiving side. What am i doing wrong?
Android Client
#Override
public void run() {
new Thread(new ClientThread()).start();
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);
while (!Thread.interrupted() && isListening && audioRecord != null) {
short[] buffer = new short[vad.getConfig().getFrameSize().getValue() * getNumberOfChannels() * 2];
audioRecord.read(buffer, 0, buffer.length);
isSpeechDetected(buffer);
}
}
private void isSpeechDetected(final short[] buffer) {
vad.isContinuousSpeech(buffer, new VadListener() {
#Override
public void onSpeechDetected() {
callback.onSpeechDetected();
spechdet = true;
byte[] bytes2 = new byte[buffer.length * 2];
ByteBuffer.wrap(bytes2).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(buffer);
totallen += bytes2.length;
try {
os = socket.getOutputStream();
os.write(bytes2, 0, minBufferSize);
}catch (Exception e){
e.printStackTrace();
s_status = false;
}
}
#Override
public void onNoiseDetected() {
callback.onNoiseDetected();
if (spechdet == true) {
try {
socket.close();
Log.w(TAG, "total length = "+ totallen);
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
spechdet = false;
totallen = 0;
new Thread(new ClientThread()).start();
}
}
}
Python Server
import pyaudio
import socket
import select
import numpy as np
import threading, collections, queue, os, os.path
from datetime import datetime
import wave
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 16000
CHUNK = 1024
audio = pyaudio.PyAudio()
stream = audio.open(format=FORMAT, channels=CHANNELS, rate=RATE, output=True, frames_per_buffer=CHUNK)
def write_wav(filename, data):
print("write wav %s", filename)
wf = wave.open(filename, 'wb')
wf.setnchannels(CHANNELS)
assert FORMAT == pyaudio.paInt16
wf.setsampwidth(2)
wf.setframerate(RATE)
wf.writeframes(data)
wf.close()
print("recording...")
with socket.socket() as server_socket:
server_socket.bind(('', 4444))
server_socket.listen(5)
wav_data = bytearray()
while True:
conn, address = server_socket.accept()
print("Connection from " + address[0] + ":" + str(address[1]))
while True:
data = conn.recv(CHUNK)
wav_data.extend(data)
stream.write(data)
if not data:
break
write_wav(os.path.join(datetime.now().strftime("savewav_%Y-%m-%d_%H-%M-%S_%f.wav")), wav_data)
print(len(wav_data))
wav_data = bytearray()
print("finished recording")
server_socket.close()
stream.stop_stream()
stream.close()
audio.terminate()
I am using this library to detect voice on client side and i have tried other methods on converting short[] to byte[] but results are same.
I've been editing androids toyvpn sample project for vpn and i got this one for my sample app
I know there is something wrong/missing with my code because when i manually set up the vpn via android settings, there are packets Receive that's why
i've been searching how to receive packets and i dont know how to get this working.
here is my source code that VCL that extends VpnService
import android.app.PendingIntent;
import android.net.VpnService;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
/**
* Created by Jameshwart Lopez on 8/18/15.
*/
public class VCL extends VpnService {
private static final String TAG = "VpnClientLibrary";
private Thread mThread;
private ParcelFileDescriptor mInterface;
private String mServerAddress;
private String mServerPort;
private PendingIntent mConfigureIntent;
private String mParameters;
//a. Configure a builder for the interface.
Builder builder = new Builder();
public void vclRun(){
try {
//a. Configure the TUN and get the interface.
mInterface = builder.setSession("thesessionname")
.addAddress("192.168.0.1",24)
.addDnsServer("8.8.8.8")
.addRoute("0.0.0.0", 0).establish();
//b. Packets to be sent are queued in this input stream.
FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());
//b. Packets received need to be written to this output stream.
FileOutputStream out = new FileOutputStream(mInterface.getFileDescriptor());
// Allocate the buffer for a single packet.
ByteBuffer packet = ByteBuffer.allocate(32767);
//c. The UDP channel can be used to pass/get ip package to/from server
DatagramChannel tunnel = DatagramChannel.open();
// Connect to the server, localhost is used for demonstration only.
mServerAddress="";//some of the vpn ip address here
mServerPort="1723";
InetSocketAddress server = new InetSocketAddress(mServerAddress, Integer.parseInt(mServerPort) );
tunnel.connect(server);
// For simplicity, we use the same thread for both reading and
// writing. Here we put the tunnel into non-blocking mode.
tunnel.configureBlocking(false);
// Authenticate and configure the virtual network interface.
handshake(tunnel);
//d. Protect this socket, so package send by it will not be feedback to the vpn service.
protect(tunnel.socket());
int timer = 0;
//e. Use a loop to pass packets.
while (true) {
//get packet with in
//put packet to tunnel
//get packet form tunnel
//return packet with out
//sleep is a must
// Assume that we did not make any progress in this iteration.
boolean idle = true;
// Read the outgoing packet from the input stream.
int length = in.read(packet.array());
if (length > 0) {
// Write the outgoing packet to the tunnel.
packet.limit(length);
tunnel.write(packet);
packet.clear();
// There might be more outgoing packets.
idle = false;
// If we were receiving, switch to sending.
if (timer < 1) {
timer = 1;
}
}
// Read the incoming packet from the tunnel.
length = tunnel.read(packet);
if (length > 0) {
// Ignore control messages, which start with zero.
if (packet.get(0) != 0) {
// Write the incoming packet to the output stream.
out.write(packet.array(), 0, length);
}
packet.clear();
// There might be more incoming packets.
idle = false;
// If we were sending, switch to receiving.
if (timer > 0) {
timer = 0;
}
}
// If we are idle or waiting for the network, sleep for a
// fraction of time to avoid busy looping.
if (idle) {
Thread.sleep(100);
// Increase the timer. This is inaccurate but good enough,
// since everything is operated in non-blocking mode.
timer += (timer > 0) ? 100 : -100;
// We are receiving for a long time but not sending.
if (timer < -15000) {
// Send empty control messages.
packet.put((byte) 0).limit(1);
for (int i = 0; i < 3; ++i) {
packet.position(0);
tunnel.write(packet);
}
packet.clear();
// Switch to sending.
timer = 1;
}
// We are sending for a long time but not receiving.
//if (timer > 20000) {
// throw new IllegalStateException("Timed out");
//}
}
}
} catch (Exception e) {
// Catch any exception
e.printStackTrace();
} finally {
try {
if (mInterface != null) {
mInterface.close();
mInterface = null;
}
} catch (Exception e) {
}
}
}
private void handshake(DatagramChannel tunnel) throws Exception {
// To build a secured tunnel, we should perform mutual authentication
// and exchange session keys for encryption. To keep things simple in
// this demo, we just send the shared secret in plaintext and wait
// for the server to send the parameters.
// Allocate the buffer for handshaking.
ByteBuffer packet = ByteBuffer.allocate(1024);
// Control messages always start with zero.
String password = "";//vpn password here
packet.put((byte) 0).put(password.getBytes()).flip();
// Send the secret several times in case of packet loss.
for (int i = 0; i < 3; ++i) {
Log.e("packetsdata", packet.toString());
packet.position(0);
tunnel.write(packet);
}
packet.clear();
// Wait for the parameters within a limited time.
for (int i = 0; i < 50; ++i) {
Thread.sleep(100);
// Normally we should not receive random packets.
int length = tunnel.read(packet);
if (length > 0 && packet.get(0) == 0) {
configure(new String(packet.array(), 1, length - 1).trim());
return;
}
}
//throw new IllegalStateException("Timed out");
}
private void configure(String parameters) throws Exception {
// If the old interface has exactly the same parameters, use it!
if (mInterface != null) {
Log.i(TAG, "Using the previous interface");
return;
}
// Configure a builder while parsing the parameters.
Builder builder = new Builder();
for (String parameter : parameters.split(" ")) {
String[] fields = parameter.split(",");
try {
switch (fields[0].charAt(0)) {
case 'm':
builder.setMtu(Short.parseShort(fields[1]));
break;
case 'a':
builder.addAddress(fields[1], Integer.parseInt(fields[2]));
break;
case 'r':
builder.addRoute(fields[1], Integer.parseInt(fields[2]));
break;
case 'd':
builder.addDnsServer(fields[1]);
break;
case 's':
builder.addSearchDomain(fields[1]);
break;
}
} catch (Exception e) {
throw new IllegalArgumentException("Bad parameter: " + parameter);
}
}
// Close the old interface since the parameters have been changed.
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
// Create a new interface using the builder and save the parameters.
mInterface = builder.setSession(mServerAddress)
.setConfigureIntent(mConfigureIntent)
.establish();
mParameters = parameters;
Log.i(TAG, "New interface: " + parameters);
}
}
this is how i use the class above
private Thread mThread;
/*
* Services interface
* */
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Start a new session by creating a new thread.
mThread = new Thread(this, "VpnRunnable");
//start the service
mThread.start();
/*
*service is left "started" and will later be restarted by the system
* http://android-developers.blogspot.com.au/2010/02/service-api-changes-starting-with.html
*/
return START_STICKY;
}
#Override
public void onDestroy() {
if (mThread != null) {
mThread.interrupt();
}
super.onDestroy();
}
#Override
public synchronized void run() {
/*
* to run the vpn interface call the vclRun method inside VCL class
* */
this.vclRun();
}
Firstly, check that there are bytes being sent to your android device. As it won't be reading anything if there is nothing to receive.
Then have a look at this, as it may be messing up your connection.
You need to include this in the onStartCommand:
// The handler is only used to show messages.
if (mHandler == null) {
mHandler = new Handler(this);
}
// Stop the previous session by interrupting the thread.
if (mThread != null) {
mThread.interrupt();
}
// Extract information from the intent.
String prefix = getPackageName();
mServerAddress = intent.getStringExtra(prefix + ".ADDRESS");
mServerPort = intent.getStringExtra(prefix + ".PORT");
mSharedSecret = intent.getStringExtra(prefix + ".SECRET").getBytes();
// Start a new session by creating a new thread.
mThread = new Thread(this, "ToyVpnThread");
mThread.start();
return START_STICKY;
And also the details (some shown below) of the sychronized void.
#Override
public synchronized void run() {
try {
Log.i(TAG, "Starting");
// If anything needs to be obtained using the network, get it now.
// This greatly reduces the complexity of seamless handover, which
// tries to recreate the tunnel without shutting down everything.
// In this demo, all we need to know is the server address.
InetSocketAddress server = new InetSocketAddress(
mServerAddress, Integer.parseInt(mServerPort));
// We try to create the tunnel for several times. The better way
// is to work with ConnectivityManager, such as trying only when
// the network is avaiable. Here we just use a counter to keep
// things simple.
for (int attempt = 0; attempt < 10; ++attempt) {
mHandler.sendEmptyMessage(R.string.connecting);
// Reset the counter if we were connected.
// See BELOW
if (run(server)) {
attempt = 0;
}
// Sleep for a while. This also checks if we got interrupted.
Thread.sleep(3000);
} /..../
You are not managing your thread actions well. It is advised to receive any bytes that need to be received before attempting your run. That not doing so can cause problems.
I would go back through your code and put in the things you took out.
I also suggest you change your code here:
packet.put((byte) 0).put(password.getBytes()).flip();
Try to use explicit encoding:
packet.put((byte) 0).put(password.getBytes("UTF-8")).flip();
As data can be lost without it. See this answer:
https://stackoverflow.com/a/7947911/3956566
I have checked and your project is using "UTF-8".
Let me know if this doesn't help.
I am using JSch to perform an SFTP download in Android. This is on a LAN with 802.11n and an SFTP server on a wired gigabit connection. I am getting about 8 mbytes/sec on a laptop (also 802.11n) with the same code but I am only getting 40kbytes/sec on Android. Are there some flags or something I need to turn on to get this to transfer faster? I have tried it on a Nexus 5 and a Nexus 6, both with 5.1. I tried a couple of apps and one downloaded the file at 230kbytes/sec and the other right around 40kbytes/sec so I'm guessing one of them has the same issue I do.
Here is my code:
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread thread = new Thread() {
#Override
public void run() {
try {
JSch jsch = new JSch();
jsch.setConfig("StrictHostKeyChecking", "no");
Session session = jsch.getSession("ftptest", "192.168.1.205");
session.setPort(22);
session.setPassword("password");
session.connect();
ChannelSftp channel = (ChannelSftp) session.openChannel("sftp");
channel.connect();
SftpProgressMonitor monitor = new SftpProgressMonitor() {
long finalCount = 0;
long start = -1;
#Override
public void init(int op, String src, String dest, long max) {
start = System.currentTimeMillis();
}
#Override
public boolean count(long count) {
finalCount += count;
/* long took = (System.currentTimeMillis() - start) / 1000;
if (took > 0) {
Log.w("SFTP", "Transferred so far " + finalCount + " at speed bytes/sec " + (finalCount / took));
}*/
return true;
}
#Override
public void end() {
long took = (System.currentTimeMillis() - start) / 1000;
Log.w("SFTP", "Transferred " + finalCount + " in " + took + " speed bytes/sec " + (finalCount / took ));
}
};
InputStream stream = channel.get("file", monitor);
int read = -1;
byte[] bs = new byte[8192];
while((read = stream.read(bs)) >= 0){
//do nothing
}
} catch (JSchException e) {
e.printStackTrace();
} catch (SftpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
thread.start();
}
}
EDIT: It seems to be much faster (about 160kbytes/sec) if I tell it to write the stream into a file without giving me an InputStream. The code looks pretty different between the two get methods but even if I went that route, 160kbytes/sec is still much slower than I had hoped.
What version of Android are you testing with? Can you adb shell in and see what these settings are (when you're on wifi)?
cat /proc/sys/net/ipv4/tcp_rmem
cat /proc/sys/net/ipv4/tcp_wmem
And then if they are low (something like "4092 8760 11680"), then try setting them to larger values:
sudo echo "524288,1048576,2097152" > /proc/sys/net/ipv4/tcp_rmem
sudo echo "262144,524288,1048576" > /proc/sys/net/ipv4/tcp_wmem
Then try your test again.
This could be from a bug where the wifi buffers were being set too small in some cases (https://code.google.com/p/android/issues/detail?id=64706).
Have you tried wrapping your stream in a buffering stream?
BufferedInputStream bis = new BufferedInputStream(channel.get("file", monitor));
8192 bytes seems like a small buffer...
Also make sure you close your connections/streams, maybe you have a lot of outgoing connections you don't know about that's hogging the hardware?
I'll try to be as descriptive as possible
I'm new to android and i'm making an android application
In that application i'd like to be able to see the address of the HTTP requests going OUT from the mobile (On what website they are heading).
So i've looked around and i found out that to do that , I need to use a VPN and android 4.0+ has a VPNService supplied from google implemented using ToyVPNService
So i got this service and started changing in it so i can use it without the need of using a server
I'd like to work the VPN as follows:
1-Capture the HTTP requests
2-Read their destination
3-Resend them back to their way
So i took the VPNService and i started modifying it so that i don't need an actual server
Here's the code i'm using
package com.example.testingservice;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.net.VpnService;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.widget.Toast;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.util.Enumeration;
public class SO1 extends VpnService implements Handler.Callback, Runnable {
private static final String TAG = "ToyVpnService";
private Handler mHandler;
private Thread mThread;
private ParcelFileDescriptor mInterface;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// The handler is only used to show messages.
if (mHandler == null) {
mHandler = new Handler(this);
}
// Stop the previous session by interrupting the thread.
if (mThread != null) {
mThread.interrupt();
}
// Start a new session by creating a new thread.
mThread = new Thread(this, "ToyVpnThread");
mThread.start();
return START_STICKY;
}
#Override
public void onDestroy() {
if (mThread != null) {
mThread.interrupt();
}
}
#Override
public boolean handleMessage(Message message) {
if (message != null) {
Toast.makeText(this, message.what, Toast.LENGTH_SHORT).show();
}
return true;
}
#Override
public synchronized void run() {
Log.i(TAG,"running vpnService");
try {
runVpnConnection();
} catch (Exception e) {
e.printStackTrace();
//Log.e(TAG, "Got " + e.toString());
} finally {
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
mInterface = null;
mHandler.sendEmptyMessage(R.string.disconnected);
Log.i(TAG, "Exiting");
}
}
private boolean runVpnConnection() throws Exception {
configure();
FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());
// Allocate the buffer for a single packet.
ByteBuffer packet = ByteBuffer.allocate(32767);
// We keep forwarding packets till something goes wrong.
while (true) {
// Assume that we did not make any progress in this iteration.
boolean idle = true;
// Read the outgoing packet from the input stream.
int length = in.read(packet.array());
if (length > 0) {
Log.i(TAG,"************new packet");
System.exit(-1);
while (packet.hasRemaining()) {
Log.i(TAG,""+packet.get());
//System.out.print((char) packet.get());
}
packet.limit(length);
// tunnel.write(packet);
packet.clear();
// There might be more outgoing packets.
idle = false;
}
Thread.sleep(50);
}
}
public String getLocalIpAddress()
{
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
Log.i(TAG,"****** INET ADDRESS ******");
Log.i(TAG,"address: "+inetAddress.getHostAddress());
Log.i(TAG,"hostname: "+inetAddress.getHostName());
Log.i(TAG,"address.toString(): "+inetAddress.getHostAddress().toString());
if (!inetAddress.isLoopbackAddress()) {
//IPAddresses.setText(inetAddress.getHostAddress().toString());
Log.i(TAG,"IS NOT LOOPBACK ADDRESS: "+inetAddress.getHostAddress().toString());
return inetAddress.getHostAddress().toString();
} else{
Log.i(TAG,"It is a loopback address");
}
}
}
} catch (SocketException ex) {
String LOG_TAG = null;
Log.e(LOG_TAG, ex.toString());
}
return null;
}
private void configure() throws Exception {
// If the old interface has exactly the same parameters, use it!
if (mInterface != null) {
Log.i(TAG, "Using the previous interface");
return;
}
// Configure a builder while parsing the parameters.
Builder builder = new Builder();
String SS=getLocalIpAddress();
builder.setMtu(1500);
// builder.addAddress("10.0.0.2", 24);
builder.addAddress(SS, 24);
// builder.addAddress(SS,24);
builder.addRoute("0.0.0.0",0);
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
mInterface = builder.establish();
}}
The problem is this line
mInterface = builder.setSession("GITVPN").setConfigureIntent(mConfigureIntent).establish();
the Establish returns NULL and i can't seem to get it working
I'm thinking there is a problem with the addresses
I'd like to work it that there's no server , and there would be a tunnel that reads the packets
I've seen some other post that said i should make the addresses to 10.0.0.2 instead of external ips ( 192.168.x.x) and i should add route (0.0.0.0,0)
However the descriptor file keeps returning null and i can't seem to fix it
Any help will be appreciated , and sorry if this sounded that it was repeated but i'm super stuck and you guys are my only hope
You can't run the VpnService and establish a VPN connection without having a server that you communicate with and forwards the traffic to the internet.
Check the IP address you assigned to the interface, it should not be the same as other adapters.
What the builder operated on is a TUN device, which is created for VPN service.
So, IP address of the TUN should be proper set.
Make the address conflict with others is not a good idea.
Also, Step 3 you mentioned is not quite easy as Android not support raw socket.
just to revive an old thread...
VpnService requires a users interaction to start and won't work without it
the ToyVpnClient puts a button on the screen that the user has to click and once that's done, the Builder method will return the interface
so, steps to make it work are;
1. build a button on your app
2. onclick of that button, call VpnService.prepare(this); (this = your app context)
3. Builder.establish() will now return a VPN interface
I'm sorry if this is a very general question but I don't know where to start so I'm looking for ideas.
I have a windows app (music score editing) and I'm currently porting it to Andriod which is coming along well.
I would like to add the feature than documents created in the windows app can be sent to the users android tablet. I was wondering, how would I write some kind of listener on Android that the windows side could open a socket or something to and send data across to it, assuming both are on the same local network.
thanks
I think sending files directly over a local network isn't the best approach. You are prone to many user complaints that the sharing isn't working.. and this will mostly be due to their own network configuration issues.
Why not use a service like DropBox to implement file sharing?
Services like DropBox offer simple API that can be used in apps in order to save files into a remote folder, and read files from a remote folder.
This way, users will not have to be in the same network at all.. and most of the heavy-lifting of implementing file sharing will be done by a service that is focused around that.
Addition:
If you don't want to require an account for a separate service like DropBox, consider this approach: Implement a very simple DropBox-like service on your own web server. Make a simple script that will allow users to upload a file to your server anonymously via HTTP. After upload, they will receive a 5 digit id for this file, or some other link they could share. When using this id or link from the 2nd app, the file could be downloaded (again via HTTP). If you delete files automatically from the server after a few hours, you will not run out of space.
You can implement such a service with about 20 lines of PHP code. And the required apps code is extremely simple (since it only relies on HTTP). If you're worried about the costs of a web server, you can get one from about $5/month or even use a free service like Google App Engine (free if your bandwidth+space requirements are low).
Code example for the file upload. Downloading should be simple enough to do alone. Regarding the periodical file delete - the obvious approach is cron but I think it's easy to manage without it. Whenever you accept a new upload (in the PHP script), go over all the downloads and delete old ones.
i wrote a small thing so my windows app can find an instance of my android app running on the local network, here it is. this is the android code first
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import android.os.AsyncTask;
import android.util.Log;
public class TabSyncServer extends AsyncTask<Void, Void, Void> {
ServerSocket mServerSocket = null;
Socket mSocket = null;
DataInputStream mDataInputStream = null;
DataOutputStream mDataOutputStream = null;
#Override
protected void onPreExecute() {
try {
mServerSocket = new ServerSocket(2112);
//System.out.println("Listening :2112");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
protected Void doInBackground(Void... args) {
byte[] bytebuf = new byte[1024];
while (true) {
try {
mSocket = mServerSocket.accept();
mDataInputStream = new DataInputStream(mSocket.getInputStream());
mDataOutputStream = new DataOutputStream(mSocket.getOutputStream());
Log.d("TabSyncServer", "ip: " + mSocket.getInetAddress());
mDataInputStream.read(bytebuf);
String str = new String(bytebuf, "UTF8");
Log.d("TabSyncServer", "message: " + str);
if(str.contains("Hello Android")) {
Log.d("TabSyncServer", "sending reply");
mDataOutputStream.writeBytes("Hello Windows");
}
//
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (mSocket != null) {
try {
mSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (mDataInputStream != null) {
try {
mDataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (mDataOutputStream != null) {
try {
mDataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
and the windows MFC code
void CMainFrame::OnBrowseMobile() {
CMobileSync* con = new CMobileSync();
CString ipaddr_base;
int my_last_digit;
if(!con->getMyIP(ipaddr_base, my_last_digit)) {
setMobilePath("Can't find local network");
return;
}
for(int i=1 ; i<98 ; i++) {
if(i==my_last_digit)
continue; // don;t check self
CString ipaddr; ipaddr.Format("%s.%d", ipaddr_base, i);
bool res = con->ConnectToHost(ipaddr);
if(res) {
res = con->SendMsg ("Hello Android");
if(res) {
TRACE1("send ok %s\n",ipaddr.GetBuffer());
#define RD_BUF_LEN 80
char buffer[RD_BUF_LEN];
if(con->ListenOnPortBlocking(buffer, RD_BUF_LEN)) {
if(strncmp(buffer, "Hello Windows", 12)==0) {
TRACE1("reply ok %s", buffer);
setMobilePath(ipaddr);
con->CloseConnection ();
return;
}
}
} else {
TRACE("send FAILED\n");
}
}
con->CloseConnection ();
}
setMobilePath("No TabTrax on local network");
}
#include "stdafx.h"
#include <winsock.h>
#include "MobileSync.h"
#define TTPORT 2112
bool CMobileSync::getMyIP(CString& ipaddr_front, int& ipaddr_lastdigit)
{
char szBuffer[1024];
#ifdef WIN32
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 0);
if(::WSAStartup(wVersionRequested, &wsaData) != 0)
return false;
#endif
if(gethostname(szBuffer, sizeof(szBuffer)) == SOCKET_ERROR)
{
#ifdef WIN32
WSACleanup();
#endif
return false;
}
struct hostent *host = gethostbyname(szBuffer);
if(host == NULL)
{
#ifdef WIN32
WSACleanup();
#endif
return false;
}
//Obtain the computer's IP
unsigned char b1, b2, b3, b4;
b1 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b1;
b2 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b2;
b3 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b3;
b4 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b4;
ipaddr_front.Format("%d.%d.%d", b1, b2, b3);
ipaddr_lastdigit = b4;
#ifdef WIN32
WSACleanup();
#endif
return true;
}
//CONNECTTOHOST – Connects to a remote host
bool CMobileSync::ConnectToHost(const char* IPAddress)
{
//Start up Winsock…
WSADATA wsadata;
int error = WSAStartup(0x0202, &wsadata);
//Did something happen?
if (error)
return false;
//Did we get the right Winsock version?
if (wsadata.wVersion != 0x0202)
{
WSACleanup(); //Clean up Winsock
return false;
}
//Fill out the information needed to initialize a socket…
SOCKADDR_IN target; //Socket address information
target.sin_family = AF_INET; // address family Internet
target.sin_port = htons (TTPORT); //Port to connect on
target.sin_addr.s_addr = inet_addr (IPAddress); //Target IP
mSocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create socket
if (mSocket == INVALID_SOCKET)
{
return false; //Couldn't create the socket
}
//Try connecting...
if (connect(mSocket, (SOCKADDR *)&target, sizeof(target)) == SOCKET_ERROR)
{
return false; //Couldn't connect
}
return true; //Success
}
//CLOSECONNECTION – shuts down the socket and closes any connection on it
void CMobileSync::CloseConnection ()
{
//Close the socket if it exists
if (mSocket)
closesocket(mSocket);
mSocket=0;
WSACleanup(); //Clean up Winsock
}
int CMobileSync::SendMsg (char* szpText, int buflen)
{
if(buflen==0)
buflen = strlen(szpText);
int ret = send(mSocket, szpText, buflen, 0);
TRACE1("CMobileSync::SendMsg sent %d bytes\n", ret);
return ret;
}
WSADATA w;
//LISTENONPORT – Listens on a specified port for incoming connections
//or data
bool CMobileSync::ListenOnPortBlocking(char* buffer, int buflen)
{
//Now we can start listening (allowing as many connections as possible to
//be made at the same time using SOMAXCONN). You could specify any
//integer value equal to or lesser than SOMAXCONN instead for custom
//purposes). The function will not //return until a connection request is
//made
// listen(s, SOMAXCONN);
memset(buffer, 0, sizeof(buffer)); //Clear the buffer
int iTimeout = 1600;
setsockopt( mSocket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&iTimeout, sizeof(iTimeout));
//Put the incoming text into our buffer
int ret = recv (mSocket, buffer, buflen-1, 0);
//Don't forget to clean up with CloseConnection()!
if(ret != SOCKET_ERROR)
return true;
int err = WSAGetLastError();
return false;
}
its not tested extensively but it is running
this maybe useful to someone