Transfer Files USB Mass Storage OTG - java

I have an external mass storage device connected to an Android device. There are several .BIN files in the root directory that I need to read into my app. I am able to connect to the device and receive usb permission using UsbDeviceConnection.
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String output = outputTV.getText().toString();
String action = intent.getAction();
outputTV.setText(outputTV.getText() + "\n" + " ACTION: " + action);
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (device != null) {
if (device.getInterfaceCount() > 0) {
usbIntf = device.getInterface(0);
usbEndIn = usbIntf.getEndpoint(0);
usbEndOut = usbIntf.getEndpoint(1);
usbConnection = mUsbManager.openDevice(device);
usbConnection.claimInterface(usbIntf, true);
byte[] buffer = new byte[usbEndIn.getMaxPacketSize()];
StringBuilder str = new StringBuilder();
int retVal = usbConnection.bulkTransfer(usbEndIn, buffer, usbEndIn.getMaxPacketSize(), 2000);
for (int i = 2; i < buffer.length; i++) {
if (buffer[i] != 0) {
str.append((char) buffer[i]);
}}}}}}}}};
Once I'm connected I am able to see that I have one Mass Storage interface with 2 Bulk Transfer endpoints (one in, one out).
When using usbConnection.bulkTransfer I receive -1 back and an empty buffer. So, I'm having trouble receiving data. Once past that hurdle, what will the data look like? How do I continue to pull all of the files from the device? Is there a way to transfer the data file by file to my app? Is there an all together better way of approaching this?

Well, I ended up going a totally different route with this. I am now using standard java.io.File and working my way through the directory structure. My code is not yet refined, but here is the gist of it...
private void setupFileIO() {
File storageDir = new File("/storage");
File files[] = storageDir.listFiles();
File directory = null;
if (files != null && files.length > 0) {
for (File f : files) {
if (f.isDirectory() && f.getPath().toLowerCase().contains("usb") && f.canRead()) {
directory = f;
break;
}
}
}
if (directory != null && directory.canRead()) {
File file[] = directory.listFiles();
if (file != null && file.length > 0) {
for (int i = 0; i < file.length; i++) {
String filePath = file[i].getPath();
String extension = Files.getFileExtension(filePath);
if (file[i].isFile() && file[i].canRead() && extension.equalsIgnoreCase("bin")) {
try {
byte[] r = Files.toByteArray(file[i]);
String result = BaseEncoding.base16().encode(r);
// do something with result
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}

Related

CSV writing data beside each other

I am writing to CSV file the BLE scanned results. What I am doing currently is writing all the data one below another.
The data consists of device name, rssi and mac address. For example, the CSV file looks like this -
DeviceA -85 DS:DA:AB:2B:B4:AE
DeviceB -100 2C:18:0B:2B:96:9E
DeviceA -85 DS:DA:AB:2B:B4:AE
My requireemnt is to write like this -
DeviceA -85 DS:DA:AB:2B:B4:AE DeviceB -100 2C:18:0B:2B:96:9E
DeviceA -85 DS:DA:AB:2B:B4:AE
After the last column of device A, I need to start with new column of device B instead of writing below device A.
Also for Device C, I want to write it beside Device C...And so on. Here is my code for writing to CSV.
public final String DATA_SEPARATOR = ",";
public final String LINE_SEPARATOR = System
.getProperty("line.separator");
try {
fileName = "test.csv";
path = Environment.getExternalStorageDirectory()
+ File.separator + "Documents";
path += File.separatorChar + "SampleApp";
File file = new File(path, fileName);
new File(path).mkdirs();
file.createNewFile();
fileStream = new OutputStreamWriter(new FileOutputStream(file));
fileStream.write("sep= " + DATA_SEPARATOR + LINE_SEPARATOR);
} catch (IOException e) {
e.printStackTrace();
fileStream = null;
}
private void writeElements(Object... elements) throws IOException {
if (fileStream != null) {
for (Object o : elements) {
fileStream.write(o.toString());
fileStream.write(DATA_SEPARATOR);
}
fileStream.write(LINE_SEPARATOR);
}
}
writeElements(btDeviceName, btRSSIValue, btMacId) is called from bluetoothScan() method every now and then.
How can I achieve writing beside?
Just put 2 on the same line before writing a LINE_SEPARATOR. Change what's in your writeElements to something like this:
private void writeElements(Object... elements) throws IOException {
if (fileStream != null) {
for (int index = 1; index < elements.length + 1; index++) {
String address = elements[index - 1].toString();
fileStream.write(address);
if(index % 2 == 0) fileStream.write(LINE_SEPARATOR);
else fileStream.write(DATA_SEPARATOR);
}
}
}
Testing:
Object[] elements = new Object[4];
elements[0] = "here";
elements[1] = "are";
elements[2] = "some";
elements[3] = "words";
writeElements(elements);
When opening the file:
here,are
some,words

Drive detection only detecting one drive?

Hello all I am using if (canRead && canWrite && !isFloppy && isDrive) and it only will read off the first drive it finds "C:\", I have a HDD and a SSD, it wont detect the ssd for somereason "D:\" for some reason anyehelp? Thanks.
Sorry guys slipped my mind to include the vars:
package javaapplication3;
import java.io.*;
import javax.swing.filechooser.FileSystemView;
class filler
{
public static void main(String ar[]) throws InterruptedException
{
FileSystemView fsv = FileSystemView.getFileSystemView();
File[] f = File.listRoots();
for (int i = 0; i < f.length; i++) {
String drive = f[i].getPath();
String displayName = fsv.getSystemDisplayName(f[i]);
String type = fsv.getSystemTypeDescription(f[i]);
boolean isDrive = fsv.isDrive(f[i]);
boolean isFloppy = fsv.isFloppyDrive(f[i]);
boolean canRead = f[i].canRead();
boolean canWrite = f[i].canWrite();
//(type.toLowerCase().contains("removable") || type.toLowerCase().contains("rimovibile"))
if (canRead && canWrite && !isFloppy && isDrive) {
try {
File file = new File(drive +"log_22_2112321321312.log");
if (file.createNewFile()){
System.out.println("File is created!");
}
if (file.exists()){
System.out.println("Drive found " + drive);
file.delete();
}
} catch (IOException e) {
e.printStackTrace();
}
}
if (canRead && canWrite && !isFloppy && isDrive &&(type.toLowerCase().contains("removable") || type.toLowerCase().contains("rimovibile"))) {
try {
File file = new File("log_22_2112321321312.log");
if (file.createNewFile()){
System.out.println("File is created!");
}
if (file.exists()){
System.out.println("Drive found " + drive);
file.delete();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Are you using File.listRoots()? Check the output of the following:
File[] roots = File.listRoots();
for (File r : roots)
System.out.println(r);
It's possible that your SSD is being detected but isn't passing your conditional's criteria. Code inside your conditional will only be executed if the specified condition is met. Run your code without the condition to see if the drive isn't actually being recognized, or whether it's not appearing due to a logic error or some other volume setting.

Unable to publish live stream continously without any halt via RTMP to FMS using Xuggler

I am trying to forward live RTMP streaming video from link1 to link2. But when video stops or pause at input end then my java application stops reading packets and get error 'unable to read RTMP-Header Packet'. Code is given below-
import com.xuggle.xuggler.ICodec;
import com.xuggle.xuggler.IContainer;
import com.xuggle.xuggler.IContainerFormat;
import com.xuggle.xuggler.IPacket;
import com.xuggle.xuggler.IStream;
import com.xuggle.xuggler.IStreamCoder;
import com.xuggle.xuggler.IVideoPicture;
public class XugglerRecorder
{
public static void main(String[] args)
{
String url = "rtmp://IP:PORT/live2/16_8_2013";
IContainer readContainer = IContainer.make();
readContainer.setInputBufferLength(4096);
IContainer writeContainer=IContainer.make();
//writeContainer.setInputBufferLength(0);
IContainerFormat containerFormat_live = IContainerFormat.make();
containerFormat_live.setOutputFormat("flv","rtmp://IP:PORT/live/abc", null);
int retVal= writeContainer.open("rtmp://192.168.1.198:1935/live/abc", IContainer.Type.WRITE, containerFormat_live);
//writeContainer.setInputBufferLength(0);
if (retVal < 0) {
System.err.println("Could not open output container for live stream");
System.exit(1);
}
if (readContainer.open(url, IContainer.Type.READ, null, true, false) < 0) {
throw new RuntimeException("unable to open read container");
}
IStream video = writeContainer.addNewStream(0);
if (video == null) {
throw new RuntimeException("unable to add video stream");
}
IPacket packet = IPacket.make();
while (readContainer.readNextPacket(packet) >= 0 && !packet.isKeyPacket()) {}
IStreamCoder inVideoCoder = null;
int videoStreamId = -1;
for (int i = 0; i < readContainer.getNumStreams(); ++i) {
IStream stream = readContainer.getStream(i);
IStreamCoder coder = stream.getStreamCoder();
if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO) {
inVideoCoder = coder;
videoStreamId = i;
if (inVideoCoder.open(null, null) < 0) {
throw new RuntimeException("Unable to open input video coder");
}
//for getting frame params need to decode at least one key frame
IVideoPicture picture = IVideoPicture.make(inVideoCoder.getPixelType(), 0, 0);
int bytesDecoded = inVideoCoder.decodeVideo(picture, packet, 0);
if (bytesDecoded < 0) {
throw new RuntimeException("Unable to decode video packet");
}
}
}
if (videoStreamId == -1) {
throw new RuntimeException("unable to find video stream");
}
IStreamCoder outVideoCoder = video.getStreamCoder();
outVideoCoder.setCodec(inVideoCoder.getCodec());
outVideoCoder.setHeight(inVideoCoder.getHeight());
outVideoCoder.setWidth(inVideoCoder.getWidth());
outVideoCoder.setPixelType(inVideoCoder.getPixelType());
outVideoCoder.setBitRate(inVideoCoder.getBitRate());
outVideoCoder.setTimeBase(inVideoCoder.getTimeBase());
if (outVideoCoder.open(null, null) < 0) {
throw new RuntimeException("unable to open output video coder");
}
if (writeContainer.writeHeader() < 0) {
throw new RuntimeException("unable to write header");
}
int i = 0;
doit(readContainer, packet, writeContainer);
if (writeContainer.writeTrailer() < 0) {
throw new RuntimeException("unable to write trailer");
}
}
private static void doit(IContainer readContainer, IPacket packet,
IContainer writeContainer) {
int i = 0;
while (readContainer.readNextPacket(packet) >= 0) {
if(readContainer.readNextPacket(packet)<0)
{
System.out.println("Packet null Hello");
try{
doit(readContainer, packet, writeContainer);
}catch(Exception e){e.printStackTrace();}
continue;
}
if(readContainer.readNextPacket(packet)==-1 ){
System.out.println("Packet is absent");
}
if (packet.getStreamIndex() != 0) {
continue;
}
if (writeContainer.writePacket(packet) < 0 && readContainer.readNextPacket(packet)>=0) {
try{
System.out.println(" packet sleep");
}catch(Exception e){e.printStackTrace();}
}
}
}
}
I am able to publish live video to FMS via RTMP. But unable to store save point of video before stop or pause of video streaming. If there is any time lag of input streaming then my application should keep on checking and waiting for stream instead of stopping.
Kindly help me out from this. Thanks in advance.
Any help or tips for how to debug this would be immensely appreciated.
I don't know much about Xuggler.
You might try catching Exception.
Or you might try calling doit() one more time in main method. Suppose in case if no more packets will be there to read then method doit() overs. So, it will not try to read again.
Or you can try adding something like
while (container.readPacket==null) {} at the starting of doit() OR I think it will be
while (container.readPacket!=null) {}
Try not checking for isKeyPacket and see what will happen.

InputStream does not work if used multiple times

I'm having some problems with an InputStream. I'm writing a little Android application and part of it has to fetch HTML code from a website. Generally, it works fine, but sometimes (usually the second time it's called, but it may also take a few tries to reproduce this) it will just skip the InputStream (I noticed this since it takes a few seconds while debugging, but every time it fails it will just immediately skip to the next line). Any ideas what could be causing this and how to fix it?
private class fetchdata extends AsyncTask<Void, Void, Void> {
public Activity activity;
public fetchdata(Activity a)
{
activity = a;
}
protected Void doInBackground(Void...voids)
{
String[] page = new String[16384]; //Number is just for testing, don't worry
try {
page = executeHttpGet();
} catch (Exception e) {
page[0] = "Error";
}
displayFetchedData(page);
return null;
}
public String[] executeHttpGet() throws Exception {
URL u;
InputStream is = null;
DataInputStream dis = null;
String s;
int i = 0;
int hostselection;
boolean skip;
String[] page = new String[16384];
String[] serverurls = new String[2];
addSecurityException();
SharedPreferences dataprefs = getSharedPreferences("serverdata", Context.MODE_PRIVATE);
hostselection = dataprefs.getInt("selectedhost", 0);
SharedPreferences preferences;
preferences = PreferenceManager.getDefaultSharedPreferences(activity);
serverurls[0] = preferences.getString("server01", "");
serverurls[1] = preferences.getString("server02", "");
for (int j = 0; j < 2; j++)
{
skip = false;
if (j == 0)
{
if (hostselection == 0 || hostselection == 1)
{
Authenticator.setDefault(new MyAuthenticator(activity, false));
}
else
{
skip = true;
}
}
if (j == 1)
{
if (hostselection == 0 || hostselection == 2)
{
Authenticator.setDefault(new MyAuthenticator(activity, true));
}
else
{
skip = true;
}
}
if (skip == false)
{
try {
u = new URL(serverurls[j]);
is = u.openStream(); //LINE IN QUESTION
dis = new DataInputStream(new BufferedInputStream(is));
while ((s = dis.readLine()) != null)
{
if (s.length() > 18)
{
page[i] = s;
i++;
}
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
is.close();
}
}
return page;
}
Create a BufferedInputStream out of the input stream you get, then Call mark() method with the input stream length as parameter. Call reset() when you need to reuse the stream next time.
Unrelated, but you aren't closing the DataInputStream.
Tell us more about the skipping. Is an exception raised? Is it possible that when you are running it outside of debug mode it is somehow referencing stale class files? The only thing I can imagine is that somehow your debug and normal classes are somehow different.

How to implement a universal file loader in Java?

This is what I'm trying to do:
public String load(String path) {
//...
}
load("file:/tmp/foo.txt"); // loads by absolute file name
load("classpath:bar.txt"); // loads from classpath
I think it's possible to do with JDK, but can't find out how exactly.
I can think of two approaches:
Just write plain Java code to extract the "scheme" from those URI-like strings, and then dispatch to the different code to load the file in different ways.
Register a custom URL stream handler to deal with the "classpath" case and then use URL.openStream() to open the stream to read the object.
The package documentation for java.net has some information about how stream handlers are discovered.
From my libraries omino roundabout, the two methods you'll need... I need them everywhere. The resource reader is relative to a class, at least to know which jar to read. But the path can start with / to force it back to the top. Enjoy!
(You'll have to make our own top level wrapper to look for "file:" and "classpath:".)
see also http://code.google.com/p/omino-roundabout/
public static String readFile(String filePath)
{
File f = new File(filePath);
if (!f.exists())
return null;
String result = "";
try
{
FileReader in = new FileReader(f);
boolean doing = true;
char[] bunch = new char[10000];
int soFar = 0;
while (doing)
{
int got = in.read(bunch, 0, bunch.length);
if (got <= 0)
doing = false;
else
{
String k = new String(bunch, 0, got);
result += k;
soFar += got;
}
}
} catch (Exception e)
{
return null;
}
// Strip off the UTF-8 front, if present. We hate this. EF BB BF
// see http://stackoverflow.com/questions/4897876/reading-utf-8-bom-marker for example.
// Mysteriously, when I read those 3 chars, they come in as 212,170,248. Fine, empirically, I'll strip that, too.
if(result != null && result.length() >= 3)
{
int c0 = result.charAt(0);
int c1 = result.charAt(1);
int c2 = result.charAt(2);
boolean leadingBom = (c0 == 0xEF && c1 == 0xBB && c2 == 0xBF);
leadingBom |= (c0 == 212 && c1 == 170 && c2 == 248);
if(leadingBom)
result = result.substring(3);
}
// And because I'm a dictator, fix up the line feeds.
result = result.replaceAll("\\r\\n", "\n");
result = result.replaceAll("\\r","\n");
return result;
}
static public String readResource(Class<?> aClass,String srcResourcePath)
{
if(aClass == null || srcResourcePath==null || srcResourcePath.length() == 0)
return null;
StringBuffer resultB = new StringBuffer();
URL resourceURL = null;
try
{
resourceURL = aClass.getResource(srcResourcePath);
}
catch(Exception e) { /* leave result null */ }
if(resourceURL == null)
return null; // sorry.
try
{
InputStream is = resourceURL.openStream();
final int BLOCKSIZE = 13007;
byte[] bytes = new byte[BLOCKSIZE];
int bytesRead = 0;
while(bytesRead >= 0)
{
bytesRead = is.read(bytes);
if(bytesRead > 0)
{
char[] chars = new char[bytesRead];
for(int i = 0; i < bytesRead; i++)
chars[i] = (char)bytes[i];
resultB.append(chars);
}
}
}
catch(IOException e)
{
return null; // sorry
}
String result = resultB.toString();
return result;
}
(edit -- removed a stray reference to OmString, to keep it standalone here.)

Categories

Resources