I want to develop an App for some internal Company stuff. However this needs VPN connection with a .p12 certificate.
Is there a way, that I can open a VPN connection in the App with this certificate? Or maybe an easier possibility automatically open the VPN App and connect to the chosen VPN.
Yes you can do by following:
Intent intent = VpnService.prepare(StatePermissionActivity.this);
if (intent != null) {
startActivityForResult(intent, 0);
}
Make a VPN Service:
public class UtilityVpnService extends VpnService {
//https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/net/VpnService.java
// http://stackoverflow.com/questions/32173374/packet-sent-but-cannot-received-packets
Builder builder;
private ParcelFileDescriptor mInterface;
private Thread mThread;
private IBinder mBinder = new MyBinder();
public static String VPN_STATE = "VPN_STATE";
public static int VPN_SERVICE_STOPPED = 1;
public static int VPN_SERVICE_STARTED = 2;
public static int VPN_SERVICE_RESUMED = 3;
public static int BLOCK_SINGLE_APP = 4;
public static int ALLOW_SINGLE_APP = 5;
public static int PACKAGE_NAME = 6;
public UtilityVpnService() {
}
#Override
public void onCreate() {
Context context = this;
Notification notification;
Intent notificationIntent = new Intent();
notificationIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
NotificationCompat.Builder bBuilder = new NotificationCompat.Builder(context);
Intent vpnIntent = new Intent(context, UtilityVpnService.class);
context.startService(vpnIntent);
notification = bBuilder.build();
notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
notification.flags |= Notification.FLAG_NO_CLEAR;
notification.flags |= Notification.FLAG_ONGOING_EVENT;
startForeground(54312, notification);
super.onCreate();
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onRebind(Intent intent) {
super.onRebind(intent);
}
#Override
public boolean onUnbind(Intent intent) {
return true;
}
public class MyBinder extends Binder {
public UtilityVpnService getService() {
return UtilityVpnService.this;
}
}
public void closeVpnInterface() {
try {
if (mInterface != null) {
mInterface.close();
}
} catch (Exception ex) {
ex.printStackTrace();
}
stopSelf();
}
#Override
public void onTaskRemoved(Intent rootIntent) {
Intent restartService = new Intent(getApplicationContext(), this.getClass());
restartService.setPackage(getPackageName());
PendingIntent restartServicePI = PendingIntent.getService(getApplicationContext(), 1, restartService,
PendingIntent.FLAG_ONE_SHOT);
//Restart the service once it has been killed android
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 100, restartServicePI);
alarmService.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000, restartServicePI);
}
#Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Context context = this;
initilizeVpnBuilder();
if (!CheckServiceIsRunning.isMyServiceRunning(RunningAppsIdentify.class, this)) {
Intent vpnIntent = new Intent(context, RunningAppsIdentify.class);
context.startService(vpnIntent);
}
return START_STICKY;
}
private void initilizeVpnBuilder() {
mThread = new Thread(new Thread() {
#Override
public void run() {
try {
// try {
// if (builder != null) {
// mInterface.close();
// }
// } catch (Exception ex) {
// ex.printStackTrace();
// }
// Configure the tunnel and get the interface.
// Build VPN service
builder = new Builder();
builder.setSession(getString(R.string.app_name));
// VPN address
builder.addAddress("10.1.10.1", 32);
builder.addAddress("fd00:1:fd00:1:fd00:1:fd00:1", 128);
// DNS address
builder.addDnsServer("8.8.8.8");
// Add Route
builder.addRoute("0.0.0.0", 0);
builder.addRoute("0:0:0:0:0:0:0:0", 0);
//Setting Applications which are allowed Internet
// and isInternetAllowed = True
List<AppsModel> list = AppsModel.getAppsAllowedForInternet();
for (int i = 0; i < list.size(); i++) {
builder.addDisallowedApplication(list.get(i).getAppPackage());
}
//Establish interface
mInterface = builder.establish();
// Add list of allowed applications
// Packets to be sent are queued in this input stream.
FileInputStream inputStream = new FileInputStream(mInterface.getFileDescriptor());
// Packets recieved need to be written to this output stream.
FileOutputStream outputStream = new FileOutputStream(mInterface.getFileDescriptor());
DatagramChannel tunnel = DatagramChannel.open();
tunnel.connect(new InetSocketAddress("127.0.0.1", 8087));
protect(tunnel.socket());
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
reader.mark(123);
reader.markSupported();
ByteBuffer packet = ByteBuffer.allocate(32767);
//byte[] bytes = extract(inputStream);
//byteBuffer.put(bytes,0,bytes.length);
// We keep forwarding packets till something goes wrong.
while (true) {
// Assume that we did not make any progress in this iteration.
try {
//Utils.getWifiSpeed(UtilityVpnService.this);
// Read the outgoing packet from the input stream.
int length = inputStream.read(packet.array());
if (length > 0) {
//Log.d("packet received", "" + length);
packet.limit(length);
tunnel.write(packet);
// Getting info about the packet..
//debugPacket(packet);
packet.clear();
// reading incoming packet from tunnel.
length = tunnel.read(packet);
if (length > 0) {
outputStream.write(packet.array());
packet.clear();
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
// String line = reader.readLine();
// if (line != null)
// Log.d("line", "" + line);
// Instructions
//get packet with in
//put packet to tunnel
//get packet from tunnel
// return packet with out
Thread.sleep(100);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
mThread.start();
}
#Override
public void onRevoke() {
super.onRevoke();
stopSelf();
}
private void debugPacket(ByteBuffer packet) {
int buffer = packet.get();
int version;
int headerlength;
version = buffer >> 4;
headerlength = buffer & 0x0F;
headerlength *= 4;
Log.d("Tag", "IP Version:" + version);
Log.d("Tag", "Header Length:" + headerlength);
String status = "";
status += "Header Length:" + headerlength;
buffer = packet.get(); //DSCP + EN
buffer = packet.getChar(); //Total Length
Log.d("Tag", "Total Length:" + buffer);
buffer = packet.getChar(); //Identification
buffer = packet.getChar(); //Flags + Fragment Offset
buffer = packet.get(); //Time to Live
buffer = packet.get(); //Protocol
Log.d("Tag", "Protocol:" + buffer);
status += " Protocol:" + buffer;
buffer = packet.getChar(); //Header checksum
String sourceIP = "";
buffer = packet.get(); //Source IP 1st Octet
sourceIP += ((int) buffer) & 0xFF;
sourceIP += ".";
buffer = packet.get(); //Source IP 2nd Octet
sourceIP += ((int) buffer) & 0xFF;
sourceIP += ".";
buffer = packet.get(); //Source IP 3rd Octet
sourceIP += ((int) buffer) & 0xFF;
sourceIP += ".";
buffer = packet.get(); //Source IP 4th Octet
sourceIP += ((int) buffer) & 0xFF;
Log.d("Tag", "Source IP:" + sourceIP);
status += " Source IP:" + sourceIP;
String destIP = "";
buffer = packet.get(); //Destination IP 1st Octet
destIP += ((int) buffer) & 0xFF;
destIP += ".";
buffer = packet.get(); //Destination IP 2nd Octet
destIP += ((int) buffer) & 0xFF;
destIP += ".";
buffer = packet.get(); //Destination IP 3rd Octet
destIP += ((int) buffer) & 0xFF;
destIP += ".";
buffer = packet.get(); //Destination IP 4th Octet
destIP += ((int) buffer) & 0xFF;
Log.d("Tag", "Destination IP:" + destIP);
status += " Destination IP:" + destIP;
try {
InetAddress addr = InetAddress.getByName(destIP);
String host = addr.getHostName();
Log.d("Tag", "Hostname:" + host);
} catch (UnknownHostException e) {
Log.d("Tag", "Unknown host");
}
}
#Override
public void onDestroy() {
if (mThread != null) {
mThread.interrupt();
}
super.onDestroy();
}
}
startService on onActivityResult()
Related
I am trying to make an application that connects to the arduino using the HC 05 module with three ultrasonic sensors. I was able to connect to the application and receive information from a particular sensor. But when I display the distance information of each sensor it is displayed in one text view (I would like three) but I have no idea what I could change in my code. Thanks in advance for your answer. Below I put the code in sequence: from arduino ideas, android studio app, android studio thread
int LtriggerPin = 13;
int LechoPin = 12;
int RtriggerPin = 11;
int RechoPin = 10;
int CtriggerPin = 9;
int CechoPin = 8;
int info = 0;
int state = 0;
void setup() {
Serial1.begin(9600);
pinMode(LtriggerPin, OUTPUT);
pinMode(LechoPin, INPUT);
pinMode(RtriggerPin, OUTPUT);
pinMode(RechoPin, INPUT);
pinMode(CtriggerPin, OUTPUT);
pinMode(CechoPin, INPUT);
}
void loop(){
sensor();
}
void sensor() {
int durationL, distanceL;
int durationR, distanceR;
int durationC, distanceC;
digitalWrite(LtriggerPin, HIGH);
delay(10);
digitalWrite(LtriggerPin, LOW);
durationL = pulseIn(LechoPin, HIGH);
distanceL = (durationL/2) / 29.1;
digitalWrite(RtriggerPin, HIGH);
delay(10);
digitalWrite(RtriggerPin, LOW);
durationR = pulseIn(RechoPin, HIGH);
distanceR = (durationR/2) / 29.1;
digitalWrite(CtriggerPin, HIGH);
delay(10);
digitalWrite(CtriggerPin, LOW);
durationC = pulseIn(CechoPin, HIGH);
distanceC = (durationC/2) / 29.1;
Serial1.print("Left Sensor ");
Serial1.print((String) distanceL + " cm" );
delay(500);
Serial1.println(" ");
Serial1.print("Right Sensor ");
Serial1.print((String) distanceR + " cm" );
delay(500);
Serial1.println(" ");
Serial1.print("Center Sensor ");
Serial1.print((String) distanceC + " cm" );
delay(500);
Serial1.println(" ");
Serial1.println(" ");
Serial1.println(" ");
}
//android thread
#Override
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.available();
if(bytes != 0) {
buffer = new byte[1024];
SystemClock.sleep(100); //pause and wait for rest of data. Adjust this depending on your sending speed.
bytes = mmInStream.available(); // how many bytes are ready to be read?
bytes = mmInStream.read(buffer, 0, bytes); // record how many bytes we actually read
hesler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget(); // Send the obtained bytes to the UI activity
}
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
public void write(String input) {
byte[] bytes = input.getBytes();
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
public void cancel() {
try {
sok.close();
} catch (IOException e) { }
}
// android Handler
handler = new Handler(Looper.getMainLooper()){
#Override
public void handleMessage(Message msg){
if(msg.what == MESSAGE_READ){
String readMessageL = null;
readMessageL = new String((byte[]) msg.obj, StandardCharsets.UTF_8);
TvC.setText(readMessageL);
}
if(msg.what == CONNECTING_STATUS){
char[] sConnected;
if(msg.arg1 == 1)
Tv3.setText(getString(R.string.BTConnected) + msg.obj);
else
Tv3.setText(getString(R.string.BTconnFail));
}
}
};
I have tried everything I can think of to improve the latency in decoding an h.264 stream from an ethernet camera. The camera's manufacturer states that it has a minimum latency of 50ms using their hardware to display the stream, so I know its possible. I was also able to play the stream on my computer without any delays as well.
I am developing in Android, where I am receiving the UDP packets via DatagramSocket, parsing the RTP packet, assembling the NAL units, passing them to MediaCodec where its decoding the h.264 stream via hardware decoder, and finally displaying the stream on a SurfaceView.
The stream plays perfect without any problems, except that there is a delay of approximately 610ms between what is being recorded and what is displayed. This camera will be used on a vehicle, so a 610ms delay is unacceptable.
Any advice on how to improve on this latency will be greatly appreciated.
Here is my code I have adapted from various public sources:
// configuration constants
private static final int SURFACE_WIDTH = 640;
private static final int SURFACE_HEIGHT = 480;
public static final String CSD_0 = "csd-0";
public static final String CSD_1 = "csd-1";
public static final String DURATION_US = "durationUs";
public static boolean DEBUGGING = false;
private final SurfaceView surfaceView;
private PlayerThread playerThread;
private RTPClientThread rtpSessionThread;
private ByteBuffer inputBuffer;
private MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
private MediaCodec decoder;
private Log log = LogFactory.getLog(RtpMediaDecoder.class);
private final byte[] byteStreamStartCodePrefix = {(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01};
private boolean useByteStreamFormat = true;
private int lastSequenceNumber = 0;
private boolean lastSequenceNumberIsValid = false;
private boolean sequenceError = false;
private boolean currentFrameHasError = false;
private BufferedSample currentFrame;
private ExecutorService executorService;
private enum NalType {
FULL,
STAPA,
STAPB,
MTAP16,
MTAP24,
FUA,
FUB,
UNKNOWN
}
public RtpMediaDecoder(SurfaceView surfaceView) {
this.surfaceView = surfaceView;
surfaceView.getHolder().addCallback(this);
}
public void start() {
rtpStartClient();
}
public void restart() {
rtpStopClient();
try {
sleep(500);
} catch (InterruptedException e) {
}
rtpStartClient();
}
public void release() {
rtpStopClient();
if (decoder != null) {
try {
decoder.stop();
} catch (Exception e) {
log.error("Encountered error while trying to stop decoder", e);
}
decoder.release();
decoder = null;
}
}
private void rtpStartClient() {
rtpSessionThread = new RTPClientThread();
executorService = Executors.newFixedThreadPool(1);
rtpSessionThread.start();
}
private void rtpStopClient() {
rtpSessionThread.interrupt();
executorService.shutdown();
}
public BufferedSample getSampleBuffer() throws Exception {
int inIndex = decoder.dequeueInputBuffer(-1);
if (inIndex < 0) {
throw new Exception("Didn't get a buffer from the MediaCodec");
}
inputBuffer = decoder.getInputBuffer(inIndex);
return new BufferedSample(inputBuffer, inIndex);
}
public void decodeFrame(BufferedSample decodeBuffer) throws Exception {
if (DEBUGGING) {
log.info(decodeBuffer.toString());
}
decoder.queueInputBuffer(decodeBuffer.getIndex(), 0,
decodeBuffer.getSampleSize(), 0, 0);
int outIndex = decoder.dequeueOutputBuffer(info, 0);
if (outIndex >= 0) {
// outputBuffer = decoder.getOutputBuffer(outIndex);
decoder.releaseOutputBuffer(outIndex,true);
}
// log.error("Completed frame decode: " + decodeBuffer.getRtpTimestamp() + " System Time: " + System.currentTimeMillis());
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
android.view.ViewGroup.LayoutParams layoutParams = surfaceView.getLayoutParams();
layoutParams.width = SURFACE_WIDTH; // required width
layoutParams.height = SURFACE_HEIGHT; // required height
surfaceView.setLayoutParams(layoutParams);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
log.debug("Starting player thread.");
if (playerThread == null) {
playerThread = new PlayerThread(holder.getSurface());
playerThread.start();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
public MediaFormat getMediaFormat() {
String mimeType = "video/avc";
int width = 640;
int height = 480;
MediaFormat format = MediaFormat.createVideoFormat(mimeType, width, height);
// from avconv, when streaming sample.h264.mp4 from disk
// byte[] header_sps = {0, 0, 0, 1, // header
// 0x67, 0x64, (byte) 0x00, 0x1e, (byte) 0xac, (byte) 0xd9, 0x40, (byte) 0xa0, 0x3d,
// (byte) 0xa1, 0x00, 0x00, (byte) 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x3C, 0x0F, 0x16, 0x2D, (byte) 0x96}; // sps
// byte[] header_pps = {0, 0, 0, 1, // header
// 0x68, (byte) 0xeb, (byte) 0xec, (byte) 0xb2, 0x2C}; // pps
byte[] header_sps = {0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x0a, (byte) 0xf8, 0x41, (byte) 0xa2};
byte[] header_pps = {0x00, 0x00, 0x00, 0x01, 0x68, (byte) 0xce, 0x38, (byte) 0x80};
format.setByteBuffer(CSD_0, ByteBuffer.wrap(header_sps));
format.setByteBuffer(CSD_1, ByteBuffer.wrap(header_pps));
//format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, width * height);
format.setInteger(DURATION_US, 12600000);
return format;
}
private class PlayerThread extends Thread {
private Surface surface;
public PlayerThread(Surface surface) {
this.surface = surface;
}
#Override
public void run() {
// MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", SURFACE_WIDTH, SURFACE_HEIGHT);
MediaFormat mediaFormat = getMediaFormat();
try {
String mime = mediaFormat.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("video/")) {
decoder = MediaCodec.createDecoderByType(mime);
}
// decoder = MediaCodec.createByCodecName("OMX.Intel.hw_vd.h264");
// decoder = MediaCodec.createDecoderByType("video/avc");
} catch (IOException e) {
e.printStackTrace();
}
if (decoder == null) {
log.info("Can't find video info!");
return;
}
decoder.configure(mediaFormat, surface, null, 0);
// log.error("Decoder Started, System Time: " + System.currentTimeMillis());
decoder.start();
}
}
private class RTPClientThread extends Thread {
private DatagramSocket mDataGramSocket;
#Override
public void run() {
try {
sleep(200);
} catch (InterruptedException e) {
}
try {
mDataGramSocket = new DatagramSocket(50004);
mDataGramSocket.setReuseAddress(true);
mDataGramSocket.setSoTimeout(1000);
} catch (Exception e) {
e.printStackTrace();
}
byte[] recvPacket = {0};
int seqNum = 0, prevSeqNum = 0, length = 0;
byte[] message = new byte[1450];
DatagramPacket p = new DatagramPacket(message, message.length);
try {
while (!Thread.interrupted()) {
try {
mDataGramSocket.receive(p);
length = p.getLength();
recvPacket = new byte[length];
System.arraycopy(message,0,recvPacket,0,length);
seqNum = ((message[2] & 0xff) << 8) | (message[3] & 0xff);
if(seqNum != prevSeqNum) {
prevSeqNum = seqNum;
if (!executorService.isTerminated() && !executorService.isShutdown()) {
executorService.execute(new PacketRunnable(recvPacket, seqNum));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
log.error("We Stopped");
mDataGramSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public class PacketRunnable implements Runnable {
private byte[] data;
private int localSeqNum;
private PacketRunnable(byte[] _data, int _seqNum) {
this.data = _data;
this.localSeqNum = _seqNum;
}
public void run() {
DataPacket packet = DataPacket.decode(data);
String debugging = "RTP data. ";
debugging += packet.getDataSize() + "b ";
debugging += "#" + packet.getSequenceNumber();
debugging += " " + packet.getTimestamp();
if (lastSequenceNumberIsValid && ((lastSequenceNumber + 1) != localSeqNum) && (localSeqNum != 0)) {
sequenceError = true;
log.error("Seq#: "+ localSeqNum + " PrevSeq#: " + lastSequenceNumber + " SKIPPED (" + (localSeqNum - lastSequenceNumber - 1) + ")");
debugging += " SKIPPED (" + (localSeqNum - lastSequenceNumber - 1) + ")";
} else {
sequenceError = false;
}
if (RtpMediaDecoder.DEBUGGING) {
log.error(debugging);
}
H264Packet h264Packet = new H264Packet(packet);
if (h264Packet.getNRIBits() > 0) {
switch (h264Packet.h264NalType) {
case FULL:
if (RtpMediaDecoder.DEBUGGING) {
log.info("NAL: full packet");
}
startFrame(packet.getTimestamp());
if (currentFrame != null) {
if (useByteStreamFormat) {
currentFrame.getBuffer().put(byteStreamStartCodePrefix);
}
currentFrame.getBuffer().put(packet.getData().toByteBuffer());
sendFrame();
}
break;
case FUA:
if (h264Packet.isStart()) {
if (RtpMediaDecoder.DEBUGGING) {
log.info("FU-A start found. Starting new frame");
}
startFrame(packet.getTimestamp());
if (currentFrame != null) {
// Add stream header
if (useByteStreamFormat) {
currentFrame.getBuffer().put(byteStreamStartCodePrefix);
}
byte reconstructedNalTypeOctet = h264Packet.getNalTypeOctet();
currentFrame.getBuffer().put(reconstructedNalTypeOctet);
}
}
if (currentFrame != null) {
if (packet.getTimestamp() != currentFrame.getRtpTimestamp()) {
if (RtpMediaDecoder.DEBUGGING) {
log.warn("Non-consecutive timestamp found");
}
currentFrameHasError = true;
}
if (sequenceError) {
currentFrameHasError = true;
}
// If we survived possible errors, collect data to the current frame buffer
if (!currentFrameHasError) {
currentFrame.getBuffer().put(packet.getData().toByteBuffer(2, packet.getDataSize() - 2));
} else {
if (RtpMediaDecoder.DEBUGGING) {
log.info("Dropping frame");
}
}
if (h264Packet.isEnd()) {
if (RtpMediaDecoder.DEBUGGING) {
log.info("FU-A end found. Sending frame!");
}
try {
sendFrame();
} catch (Throwable t) {
log.error("Error sending frame.", t);
}
}
}
break;
case STAPA:
if (RtpMediaDecoder.DEBUGGING) {
log.info("NAL: STAP-A");
}
ChannelBuffer buffer = packet.getData();
buffer.readByte();
while (buffer.readable()) {
short nalUnitSize = buffer.readShort();
byte[] nalUnitData = new byte[nalUnitSize];
buffer.readBytes(nalUnitData);
startFrame(packet.getTimestamp());
if (currentFrame != null) {
if (useByteStreamFormat) {
currentFrame.getBuffer().put(byteStreamStartCodePrefix);
}
currentFrame.getBuffer().put(nalUnitData);
sendFrame();
}
}
break;
case STAPB:
case MTAP16:
case MTAP24:
case FUB:
case UNKNOWN:
log.warn("NAL: Unimplemented unit type: " + h264Packet.getNalType());
break;
}
} else {
log.warn("Useless packet received.");
}
lastSequenceNumber = localSeqNum;
lastSequenceNumberIsValid = true;
}
}
}
private void startFrame(long rtpTimestamp) {
// Reset error bit
currentFrameHasError = false;
// Deal with potentially non-returned buffer due to error
if (currentFrame != null) {
currentFrame.getBuffer().clear();
// Otherwise, get a fresh buffer from the codec
} else {
try {
// Get buffer from decoder
currentFrame = getSampleBuffer();
currentFrame.getBuffer().clear();
} catch (Exception e) {
currentFrameHasError = true;
e.printStackTrace();
}
}
if (!currentFrameHasError) {
// Set the sample timestamp
currentFrame.setRtpTimestamp(rtpTimestamp);
}
}
private void sendFrame() {
currentFrame.setSampleSize(currentFrame.getBuffer().position());
currentFrame.getBuffer().flip();
// log.error("Sending Frame: " + currentFrame.getRtpTimestamp() + " System Time: " + System.currentTimeMillis());
try {
decodeFrame(currentFrame);
} catch (Exception e) {
log.error("Exception sending frame to decoder", e);
}
// Always make currentFrame null to indicate we have returned the buffer to the codec
currentFrame = null;
}
private class H264Packet {
private final byte nalFBits;
private final byte nalNriBits;
private final byte nalType;
private boolean fuStart = false;
private boolean fuEnd = false;
private byte fuNalType;
private NalType h264NalType = NalType.UNKNOWN;
public H264Packet(DataPacket packet) {
// Parsing the RTP Packet - http://www.ietf.org/rfc/rfc3984.txt section 5.3
byte nalUnitOctet = packet.getData().getByte(0);
nalFBits = (byte) (nalUnitOctet & 0x80);
nalNriBits = (byte) (nalUnitOctet & 0x60);
nalType = (byte) (nalUnitOctet & 0x1F);
// If it's a single NAL packet then the entire payload is here
if (nalType > 0 && nalType < 24) {
h264NalType = NalType.FULL;
} else if (nalType == 24) {
h264NalType = NalType.STAPA;
} else if (nalType == 25) {
h264NalType = NalType.STAPB;
} else if (nalType == 26) {
h264NalType = NalType.MTAP16;
} else if (nalType == 27) {
h264NalType = NalType.MTAP24;
} else if (nalType == 28) {
h264NalType = NalType.FUA;
} else if (nalType == 29) {
h264NalType = NalType.FUB;
}
byte fuHeader = packet.getData().getByte(1);
fuStart = ((fuHeader & 0x80) != 0);
fuEnd = ((fuHeader & 0x40) != 0);
fuNalType = (byte) (fuHeader & 0x1F);
}
public byte getNalTypeOctet() {
// Excerpt from the spec:
/* "The NAL unit type octet of the fragmented
NAL unit is not included as such in the fragmentation unit payload,
but rather the information of the NAL unit type octet of the
fragmented NAL unit is conveyed in F and NRI fields of the FU
indicator octet of the fragmentation unit and in the type field of
the FU header" */
return (byte) (fuNalType | nalFBits | nalNriBits);
}
public boolean isStart() {
return fuStart;
}
public boolean isEnd() {
return fuEnd;
}
public byte getNalType() {
return nalType;
}
public byte getNRIBits() {
return nalNriBits;
}
}
}
I use the common tcp client to receive string messages through TCP.
I want after the reception of a specific message e.g. "XXX" my client to be ready to receive a bmp image.
My server in C++ sends the messages but the client does not receive the image...
After some suggestions .. se below I udated the code...
Here is my code:
TCP client:
public class TCPClient {
private String serverMessage;
public static final String SERVERIP = "192.168.1.88"; //your computer IP
public static final int SERVERPORT = 80;
private OnMessageReceived mMessageListener = null;
private boolean mRun = false;
private PrintWriter out;
private BufferedReader input;
private DataInputStream dis;
/**
* Constructor of the class. OnMessagedReceived listens for the messages received from server
*/
public TCPClient(OnMessageReceived listener) {
mMessageListener = listener;
}
/**
* Sends the message entered by client to the serveraddress
* #param message text entered by client
*/
public void sendMessage(String message){
if (out != null && !out.checkError()) {
out.println(message);
out.flush();
}
}
public void stopClient(){
mRun = false;
if (out != null) {
out.flush();
out.close();
}
mMessageListener = null;
input = null;
input = null;
input = null;
serverMessage = null;
}
public void run() {
mRun = true;
try {
//here you must put your computer's IP address.
InetAddress serverAddr = InetAddress.getByName(SERVERIP);
Log.e("TCP Client", "C: Connecting...");
//create a socket to make the connection with the server
Socket socket = new Socket(serverAddr, SERVERPORT);
try {
//send the message to the server
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
Log.e("TCP Client", "C: Sent.");
Log.e("TCP Client", "C: Done.");
//receive the message which the server sends back
dis = new DataInputStream(socket.getInputStream());
// The buffer reader cannot can't wrap an InputStream directly. It wraps another Reader.
// So inputstreamreader is used.
input = new BufferedReader(new InputStreamReader(dis, "UTF-8"));
Log.d("MyApp","We are here");
//this.input = new DataInputStream(in);
//in this while the client listens for the messages sent by the server
while (mRun) {
Log.d("MyApp", "We are here 2");
serverMessage = input.readLine();
if (serverMessage != null && mMessageListener != null) {
//call the method messageReceived from MyActivity class
mMessageListener.messageReceived(serverMessage);
Log.d("RESPONSE FROM SERVER", "S: Received Message: '" + serverMessage + "'");
}
if ("XXX".equals(serverMessage)) {
Log.d("MyApp", "We are here 3");
serverMessage = null;
while (mRun) {
WriteSDCard writeSDCard = new WriteSDCard();
writeSDCard.writeToSDFile(serverMessage);
}
}
}
} finally {
socket.close();
}
Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + serverMessage + "'");
} catch (Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
//the socket must be closed. It is not possible to reconnect to this socket
// after it is closed, which means a new socket instance has to be created.
}
}
//Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity
//class at on asynckTask doInBackground
public interface OnMessageReceived {
public void messageReceived(String message);
}
}
public class WriteSDCard extends Activity {
private static final String TAG = "MEDIA";
private TextView tv;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//(not needed) setContentView(R.layout.main);
//(not needed) tv = (TextView) findViewById(R.id.TextView01);
checkExternalMedia();
String message =null;
}
/** Method to check whether external media available and writable. This is adapted from
http://developer.android.com/guide/topics/data/data-storage.html#filesExternal */
private void checkExternalMedia(){
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// Can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// Can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// Can't read or write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
tv.append("\n\nExternal Media: readable="
+mExternalStorageAvailable+" writable="+mExternalStorageWriteable);
}
/** Method to write ascii text characters to file on SD card. Note that you must add a
WRITE_EXTERNAL_STORAGE permission to the manifest file or this method will throw
a FileNotFound Exception because you won't have write permission. */
void writeToSDFile(String inputMsg){
// Find the root of the external storage.
// See http://developer.android.com/guide/topics/data/data- storage.html#filesExternal
File root = android.os.Environment.getExternalStorageDirectory();
tv.append("\nExternal file system root: "+root);
// See http://stackoverflow.com/questions/3551821/android-write-to-sd-card-folder
File dir = new File (root.getAbsolutePath() + "/download");
dir.mkdirs();
Log.d("WriteSDCard", "Start writing");
File file = new File(dir, "myData.txt");
try {
FileOutputStream f = new FileOutputStream(file);
PrintWriter pw = new PrintWriter(f);
pw.println(inputMsg);
pw.flush();
pw.close();
f.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.i(TAG, "******* File not found. Did you" +
" add a WRITE_EXTERNAL_STORAGE permission to the manifest?");
} catch (IOException e) {
e.printStackTrace();
}
tv.append("\n\nFile written to "+file);
}
/** Method to read in a text file placed in the res/raw directory of the application. The
method reads in all lines of the file sequentially. */
}
And the server side:
Code:
void sendBMP( int cs, int xs, int ys)
{
int imgdataoffset = 14 + 40; // file header size + bitmap header size
int rowsz = ((xs) + 3) & -4; // size of one padded row of pixels
int imgdatasize = (((xs*3) + 3) & -4) * ys; // size of image data
int filesize = imgdataoffset + imgdatasize;
int i, y;
HTLM_bmp_H HTLM_bmp_h;
HTLM_bmp_h.bmfh.bfSize = filesize;
HTLM_bmp_h.bmfh.bfReserved1 = 0;
HTLM_bmp_h.bmfh.bfReserved2 = 0;
HTLM_bmp_h.bmfh.bfOffBits = imgdataoffset;
HTLM_bmp_h.bmih.biSize = 40;
HTLM_bmp_h.bmih.biWidth = xs;
HTLM_bmp_h.bmih.biHeight = ys;
HTLM_bmp_h.bmih.biPlanes = 1;
HTLM_bmp_h.bmih.biBitCount = 24;
HTLM_bmp_h.bmih.biCompression = 0;
HTLM_bmp_h.bmih.biSizeImage = imgdatasize;
HTLM_bmp_h.bmih.biXPelsPerMeter = 1000;
HTLM_bmp_h.bmih.biYPelsPerMeter = 1000;
HTLM_bmp_h.bmih.biClrUsed = 1 << 24;
HTLM_bmp_h.bmih.biClrImportant = 0;
printf("Start Sending BMP.\n");
send(cs,(unsigned char *)"BM",2,0);
send(cs,(unsigned char *)&HTLM_bmp_h,sizeof(HTLM_bmp_h),0);
printf("Sending...\n");
Buff_ptr = 0;
send(cs, (unsigned char *)Rbuffer, BUFF_SIZE,0 );
send(cs, (unsigned char *)Gbuffer, BUFF_SIZE,0 );
send(cs, (unsigned char *)Bbuffer, BUFF_SIZE,0 );
send(cs, (unsigned char *)"\n",1,0);
send(cs, (unsigned char *)"END\n",4,0);
printf("Done\n\n");
}
typedef struct {
// char bfType1;
// char bfType2;
int bfSize;
short bfReserved1;
short bfReserved2;
int bfOffBits;
} BMFH;
typedef struct {
unsigned int biSize;
int biWidth;
int biHeight;
short biPlanes;
short biBitCount;
unsigned int biCompression;
unsigned int biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
} BMIH;
typedef struct {
BMFH bmfh;
BMIH bmih;
} HTLM_bmp_H;
main()
{
TSK_Handle tsk_cam;
tsk_cam=TSK_create( (Fxn)TSK_webview, NULL);
TSK_setpri(tsk_cam, 8);
}
char buffer[2048];
Void TSK_webview()
{
int s,cs;
struct sockaddr_in addr; /* generic socket name */
struct sockaddr client_addr;
int sock_len = sizeof(struct sockaddr);
int frame = 0;
LgUns i=0;
int len;
int x = DSKeye_SXGA_WIDTH, y = DSKeye_SXGA_HEIGHT;
DSKeye_params CAM_params = {
....
};
lwIP_NetStart();
/**************************************************************
* Main loop.
***************************************************************/
s = socket( AF_INET, SOCK_STREAM, 0 );
addr.sin_port = htons(80);
addr.sin_addr.s_addr = 0;
memset(&(addr.sin_zero), 0, sizeof(addr.sin_zero));
printf("start\n");
if( bind(s, (struct sockaddr*)&addr, sizeof(struct sockaddr)))
{
printf("error binding to port\n");
return ;
}
printf("xx1\n");
if(DSKeye_open(&CAM_params)) {
printf("xx2\n");
SYS_abort("DSKcam_CAMopen");
printf("xx3\n"); fflush(stdout);}
printf("xx4\n");
while(1==1) {
printf("Waiting for client to be connected ... \n");
listen(s, 10);
cs = accept(s, &client_addr, &sock_len);
printf("Client connected.\n");
send(cs,(unsigned char *)"Server connected\n",17,0);
recv(cs, (unsigned char*)buffer, 17, 0);
switch (*(buffer)){
case 'A' :
...
case 'B' :
...
}
REG32(0xA0000080)=REG32(0xA0000080) - 0x800000; ///Disable stepper controller vhdl Quartus Block
for(frame = 0; frame < 4; frame++){ // Allow AEC etc to settle
SrcFrame=DSKeye_getFrame();
}
printf("Demosaicing of %d x %d image is ongoing \n", x, y);
demosaic(SrcFrame, x, y);
break;
}
printf("Demosaicing completed ...\n");
send(cs,(unsigned char *)"Demosaicing completed\n",22,0);
send(cs,(unsigned char *)"XXX\n",4,0);
sendBMP(cs, x, y);
fflush(stdout);
lwip_close(cs);
}
the send : lwip_send
int lwip_send(int s, void *data, int size, unsigned int flags)
{
struct lwip_socket *sock;
struct netbuf *buf;
err_t err;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%d, flags=0x%x)\n", s, data, size, flags));
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
switch (netconn_type(sock->conn)) {
case NETCONN_RAW:
case NETCONN_UDP:
case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM:
/* create a buffer */
buf = netbuf_new();
if (!buf) {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ENOBUFS\n", s));
sock_set_errno(sock, ENOBUFS);
return -1;
}
/* make the buffer point to the data that should
be sent */
netbuf_ref(buf, data, size);
/* send the data */
err = netconn_send(sock->conn, buf);
/* deallocated the buffer */
netbuf_delete(buf);
break;
case NETCONN_TCP:
err = netconn_write(sock->conn, data, size, NETCONN_COPY);
break;
default:
err = ERR_ARG;
break;
}
if (err != ERR_OK) {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d\n", s, err));
sock_set_errno(sock, err_to_errno(err));
return -1;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ok size=%d\n", s, size));
sock_set_errno(sock, 0);
return size;
}
You can't mix a buffered reader and a data input stream on the same socket. The buffered reader will read-ahead and steal data you expect to read via the data input stream. You will have to use the data input stream for everything. And correspondingly at the sender.
You're doing incorrect comparison for string equality.
In Java, string comparison for equality is done using String.equals(Object anObject)
You're using if (serverMessage == "XXX") {....
You should use if ("XXX".equals(serverMessage)) {....
I'm creating an app to read string values over Bluetooth serial port. My data receiving but in two parts. If I send $F00,A,B,0,M# via bluetooth it only reads $ in first part and F00,A,B,0,M# in next part. I provided my code here. Please do correct me if I'm wrong.
InputStream inputStream=null;
int avilableBytes=0;
public ConnectedThread(BluetoothSocket socket){
InputStream temp=null;
try{
temp=socket.getInputStream();
}catch (IOException e){
e.printStackTrace();
}
inputStream=temp;
}
public void run() {
try{
int bytes;
while (true){
try{
avilableBytes=inputStream.available();
if (avilableBytes>0){
byte[] buffer=new byte[avilableBytes];
bytes=inputStream.read(buffer);
final String readMessage=new String(buffer,0,bytes);
bt_handler.obtainMessage(handlerState,bytes,-1,readMessage).sendToTarget();
Log.d("PRAVEEN",readMessage);
}
}catch (IOException e){
e.printStackTrace();
}
}
}catch (Exception e){
e.printStackTrace();
}
}
Data are like stream bytes and can not be processed immediately when it comes with a few bytes. Data will not come all at once as a single packet. You have to use the other byte[] buffer (MainBuffer) in which you will gradually save incoming byte and move the index in that buffer. Then, from time to time (e.g. in the timer once per second) take data from the main buffer and processed it. By default you must implement some data frame with a separator (eg. Data * data * data * - Many ways to do it good or bad). I dealt with this in .net via Xamarin, but just as an example it may be helpfull :
update example, format
In ConnectedThread :
public override void Run()
{
while (true)
{
try
{
int readBytes = 0;
lock (InternaldataReadLock)
{
readBytes = clientSocketInStream.Read(InternaldataRead, 0, InternaldataRead.Length);
Array.Copy(InternaldataRead, TempdataRead, readBytes);
}
if (readBytes > 0)
{
lock (dataReadLock)
{
dataRead = new byte[readBytes];
for (int i = 0; i < readBytes; i++)
{
dataRead[i] = TempdataRead[i];
}
}
Bundle dataBundle = new Bundle();
dataBundle.PutByteArray("Data", dataRead);
Message message = btlManager.sourceHandler.ObtainMessage();
message.What = 1;
message.Data = dataBundle;
btlManager.sourceHandler.SendMessage(message);
}
}
catch (System.Exception e)
{
btlManager.btlState = BTLService.BTLState.Nothing;
}
}
}
In BTLHandler :
public override void HandleMessage(Message msg)
{
switch (msg.What)
{
case 1:
{
byte[] data = msg.Data != null ? msg.Data.GetByteArray("Data") : new byte[0];
btlService.BTLReceiveData(data);
}
break;
}
}
public void BTLReceiveData(byte[] data)
{
lock (dataReadLock)
{
for (int i = 0; i < data.Length; i++)
{
dataRead[dataReadWriteCursor] = data[i];
dataReadWriteCursor++;
}
}
}
In Timer :
int tmpWriteCursor = dataReadWriteCursor;
int tmpReadCursor = dataReadReadCursor;
lock (dataReadLock)
{
int newBytes = dataReadWriteCursor - dataReadReadCursor;
for (int i = 0; i < newBytes; i++)
{
dataReadMain[dataReadReadCursor] = dataRead[dataReadReadCursor++];
}
}
bool odradkovani = false;
string tmpRadek = "";
int lastLineIndex = 0;
List<string> list = new List<string>();
for (int i = LastWriteLineIndex; i < tmpWriteCursor; i++)
{
if (dataReadMain[i] >= 32 && dataReadMain[i] <= 255)
{
tmpRadek += (char)dataReadMain[i];
}
else if (dataReadMain[i] == 13) odradkovani = true;
else if (dataReadMain[i] == 10)
{
if (odradkovani)
{
odradkovani = false;
list.Add(Utils.GetFormatedDateTime(DateTime.Now) + " " + tmpRadek);
tmpRadek = "";
lastLineIndex = i + 1;
}
}
else
{
tmpRadek += "?" + dataReadMain[i].ToString() + "?";
}
}
WriteDataToLog(list);
LastWriteLineIndex = lastLineIndex;
how to convert 35 bytes of hex values to decimal coming from bluetooth serial port communnication.. i am using bluetooth chat application, the device sending data in hex format of 35 bytes....
my code giving output like: 10 oa ff 00 3c................11
my code..
Bluetoothservice.java
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[35];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer, 0, buffer.length);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
// Start the service over to restart listening mode
BluetoothService.this.start();
break;
}
}
MainActivity.java
byte[] readBuf = (byte[]) msg.obj;
String readMessage = BytesTrans.bytes2HexString(readBuf,msg.arg1);
mArrayAdapter.addAll(mConnectedDeviceName+": "+ readMessage );
public static class BytesTrans {
public static String bytes2HexString(byte[] b, int count) {
String ret = "";
//String str ="";
for (int i = 0; i < count; i++) {
String hex = Integer.toHexString(b[i] & 0xFF);
if (hex.length() ==1) {
hex = '0' + hex;
}
ret += hex.toUpperCase() + " ";
}
return ret;
}`
Try the following:
public static String bytes2String(byte[] b, int count) {
String ret = "";
//String str ="";
for (int i = 0; i < count; i++) {
String myInt = Integer.toString((int)(b[i] & 0xFF));
ret.append(myInt + " ");
}
return ret;
}
I think this may be what you are looking for.