Why is GetExternalFileDirs not working in android? - java

I am working on a sample project in unity android where application reads a textfile in an OTG pen drive connected to the android phone, the problem is my code works fine in some devices but it doesn't work in some devices. I am unable to figure out the main cause even through the logcat extreme as it doesn't throw any error at all that specifies code error.
I tried adding text logs to print text in between the code to see which texts are not printed, which would further tell me that after which line code stopped working but all the texts are printed.
This is my code that detects the USB and returns true if a text file is present in USB:
public void LocateFile()
{
textfileData = null;
using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
using (AndroidJavaObject context = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
{
// Get all available external file directories (emulated and USBdrives)
AndroidJavaObject[] externalFilesDirectories = context.Call<AndroidJavaObject[]>("getExternalFilesDirs", (object)null);
AndroidJavaObject emulated = null;
AndroidJavaObject USBdrive = null;
for (int i = 0; i < externalFilesDirectories.Length; i++)
{
AndroidJavaObject directory = externalFilesDirectories[i];
using (AndroidJavaClass environment = new AndroidJavaClass("android.os.Environment"))
{
bool isRemovable = environment.CallStatic<bool>("isExternalStorageRemovable", directory);
bool isEmulated = environment.CallStatic<bool>("isExternalStorageEmulated", directory);
if (isEmulated)
{
emulated = directory;
}
else if (isRemovable && isEmulated == false)
{
USBdrive = directory;
}
}
}
// Return the USBdrive if available
if (USBdrive != null)
{
if (File.Exists(USBdrive.Call<string>("getAbsolutePath") + "/serial.txt"))
{
textfileData = File.ReadAllText(USBdrive.Call<string>("getAbsolutePath") + "/serial.txt");
}
}
}
}}
This code works on my android phone and returns true after detecting the file present in pendrive.
Can anyone tell me what could be the issue and point me in the right direction, I will greatly appreciate your support on this.
This locateFile() function is called on Update().
Update: I tried to debug the number of storage found in mobile and code is not reading the USB. It reads internal and SD storage perfectly.
Nokia 5 is the only phone the code has worked on so far but in 99% android devices GetExternalFilesDir is not reading usb storage.
Please someone tell me an alternate or how do I get this to work, it is very important.

Related

How to let a sound play once in Processing?

import processing.serial.*;
import processing.sound.*;
SoundFile file;
Serial myPort; // Create object from Serial class
String val; // Data received from the serial port
//String antwoord = "A";
void setup()
{
size(300,300);
// I know that the first port in the serial list on my mac
// is Serial.list()[0].
// On Windows machines, this generally opens COM1.
// Open whatever port is the one you're using.
String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. to match your port
myPort = new Serial(this, portName, 9600);
}
void draw()
{
if ( myPort.available() > 0)
{ // If data is available,
val = trim( myPort.readStringUntil(ENTER) );
// read it and store it in val
}
//println(val); //print it out in the console
file = new SoundFile(this,"Promise.mp3");
if ("A".equals(val) == true && file.isPlaying() == false) {
file.play();
file.amp(0.2);}
else{
ellipse(40,40,40,40);
}
}
I got this code, but I want the sound to keep playing as long as the signal 'A' is given. Now it starts playing constantly, which leads to a weird static noise. How can I make it just play steadidly?
You're creating a new SoundFile in every run of draw. So file.isPlaying() will always return false. Only create a new SoundFile if you haven't already. The simplest solution is probably to move file = new SoundFile(this,"Promise.mp3"); into setup
Or you check or remember if you already loaded the file.
I am sorry if it is a bit disconnected but I recommend using minim or a different sound library instead of the processing one, since it causes a lot of problems in exporting (at least it had done so consistently for me).

NFC stops working after writing on iCODE tags, Android 6.0

I'm developing an android application to read and and write different NFC tags. I've encountered a problem with a specific tag ,iCODE SLI X and iCODE SLI S. After i write information on the tag, i'm not able to do any other action, looks like NFC stops working correctly because if i restart it, it will actually read the tag. This does not happen if i use another tag type like MIFARE Classic 1K. Android version is 6.0.
On the other hand, if i try the application on another device with Android 6.1 or 7.0 (exact same code), iCODE SLI X and iCODE SLIS will work okay, but not MIFARE Classic 1K.
Besides trying different samples of codes, i have also tried 2 applications on these devices. On "NFC Tools" you can see exactly the same problems that i have on my application. "TagWriter" from NXP is the only application that works like a charm with all types of tags.
Here is the code I'm using to write the information on the tag:
#Override
protected void onNewIntent(Intent intent) {
if (mNfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (tag != null) {
try {
Ndef ndef = Ndef.get(tag);
NdefRecord text1 = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
youstring1.getBytes(Charset.forName("US-ASCII")),
null,
youstring1.getBytes());
NdefRecord text2 = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
youstring2.getBytes(Charset.forName("US-ASCII")),
null,
youstring2.getBytes());
NdefRecord[] records = {text1, text2};
NdefMessage message = new NdefMessage(records);
if (ndef != null) {
NdefMessage ndefMesg = ndef.getCachedNdefMessage();
if (ndefMesg != null) {
ndef.connect();
ndef.writeNdefMessage(message);
ndef.close();
}
} else {
NdefFormatable ndefFormatable = NdefFormatable.get(tag);
if (ndefFormatable != null) {
// initialize tag with new NDEF message
try {
ndefFormatable.connect();
ndefFormatable.format(message);
ndefFormatable.close();
} finally {
try {
//ndefFormatable.close();
} catch (Exception e) {
}
}
}
}
}catch (FormatException |IOException ue){}
}
}
}
I can't understand what I'm possibly doing wrong ...
I managed to understand what was wrong with my application, so I'm posting the answer myself. Here is the thing :
When i try to write the information on the tag I first check if the tag is formatted to use "Ndef" technology on it, if not I use "NdefFormatable" to format the tag.
The strange thing is, a certain tag in some devices supports "NdefFormatable" and in some it doesn't. (not sure if its related to NFC itself or the OS version). This was causing NFC to misbehave or not to work at all after I tried to use "NdefFormatable".
What I'm doing now is that i have build this function that gives the technologies that I can use on the tag. Depending on it, I use "NdefFormatable" or "NfcV" (for iCODE tags) to read or write on the tag.

JNetPcap in eclipse does not print error... Ubuntu 12.04

Have some problems with JNetPcap.
I uses Ubuntu 12.04, and trying to make packet snipper that based in java language.
What I did is below.
I have downloaded JNetPcap 1.3.0.
And as tutorial said built a java project.
http://jnetpcap.com/examples/dumper <- this is the link.
I typed just like that link and I got my first problem.
PcapHandler Class is deprecated. So I find the document and replace it with ByteBufferHandler.
Now I compile this project and got an unsatifiedLinked Error.
I have tried with static block to load that library.
After some attempts I copied "libjnetpcap.so" to /usr/lib/
now I remove unsatisfiedLinked Error. but somehow it stops in 1st Error check.
It prints "1st error check : ", then exit automatically.
public static void main(String[] args) {
List<PcapIf> alldevs = new ArrayList<PcapIf>();
StringBuilder errbuff = new StringBuilder();
int r = Pcap.findAllDevs(alldevs, errbuff);
//============1st check
if(r == Pcap.NOT_OK || alldevs.isEmpty()){
System.err.printf("1st error check : %s\n", errbuff.toString());
return;
}
PcapIf device = alldevs.get(1);
//===================== END
int snaplen = 64 * 1024;
int flags = Pcap.MODE_PROMISCUOUS;
int timeout = 10 * 1000;
Pcap pcap = Pcap.openLive(device.getName(),snaplen, flags, timeout, errbuff);
//============2nd check
if(pcap == null){
System.err.printf("2nd error check : %s\n", errbuff.toString());
return;
}
//===================== END
String ofile = "/home/juneyoungoh/tmp_capture_file.cap";
final PcapDumper dumper = pcap.dumpOpen(ofile);
ByteBufferHandler<PcapDumper> handler = new ByteBufferHandler<PcapDumper>() {
#Override
public void nextPacket(PcapHeader arg0, ByteBuffer arg1, PcapDumper arg2) {
dumper.dump(arg0, arg1);
}
};
pcap.loop(10,handler, dumper);
File file = new File(ofile);
System.out.printf("%s file has %d bytes in it!\n", ofile, file.length());
dumper.close();
pcap.close();
if(file.exists()){
file.delete();
}
}
if is there any good reference or wonderful idea, please share.
Thanks.
On Linux, a program will probably have to run as root, or with sufficient privileges granted in some other fashion, in order to be able to open any devices, and, currently, pcap_findalldevs(), which is presumably what the Pcap.findAllDevs method uses, tries to open each of the devices it finds, and only returns the devices it can open.
So you'll have to run your Java program as root, or will somehow have to arrange that it have sufficient privileges (CAP_NET_RAW and CAP_NET_ADMIN) to get a list of network adapters and open those adapters.

Android SD card path synonims

I have a little bit strange question: this time everything works, but I can't understand why.
AFAIK it's possible to mount more than one sd card. Everything will be mounted to /mnt directory. (is it true?)
On my device there is only one sd card which mounted to /mnt/sdcard. And in my application I open files from it. I'm using next code:
private void open() {
// get file extension
String extension = "";
int dotIndex = downloadedFile.lastIndexOf('.');
if (dotIndex != -1) {
extension = downloadedFile.substring(dotIndex + 1, downloadedFile.length());
}
// create an intent
Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
Uri data = Uri.fromFile(new File(downloadedFile));
String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
if (type == null || type.length() == 0) {
// if there is no acceptable mime type
type = "application/octet-stream";
}
intent.setDataAndType(data, type);
// get the list of the activities which can open the file
List resolvers = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (resolvers.isEmpty()) {
(new AlertDialog.Builder(context)
.setMessage(R.string.AttachmentUnknownFileType)
.setNeutralButton(R.string.NeutralButtonText, null)
.create()).show();
} else {
context.startActivity(intent);
}
}
Actually downloadedFile variable has value like file:///sdcard/mydir/myfile.txt. But the code works. Why? How Android understand what /sdcard/... is the same as /mnt/sdcard/...?
And main question: what happened if sd card will be mounted to other dir (for exmaple, /mnt/another-sd/ or even /media/sd)? What if more than one sd cards will be mounted: how android understand what card to use?
Thank you for any help! Have a good day!
It's simple android configueres the mounting over a settings file on phone boot so if there are mor sdcards Android will simply prefer one of them to set as
/sdcard/
so when the mount settings change your code is simply useless you can only hope the settings being untouched .
Every company that procuces Android smartphones use the "sdcard" path even custom roms like use it

java.lang.nosuchfielderror in j2me app

Hey Hi Friends I am created one j2me app. it runs perfectly in Emulator but in Mobile it showing error like java.lang.nosuchfielderror:No such field HEADERS.[[Ljava/lang/String;.
Why this happening with mobile, it runs good in emulator......
Please help me to remove this error......
public String connectPhoneName() throws Exception{
String url = "http://122.170.122.186/Magic/getPhonetype.jsp";
String phoneType;
if ((conn = connectHttp.connect(url, HEADERS)) != null) {
if ((in = connectHttp.getDataInputStream(conn)) != null) {
byte[] data = connectHttp.readDATA(in, 100);
phoneType = new String(data);
System.out.println("DATA : " + phoneType);
} else {
throw new Exception("ERROR WHILE OPENING INPUTSTREAM");
}
} else {
throw new Exception("COULD NOT ESTABLISH CONNECTION TO THE SERVER");
}
return phoneType;
}
In this code i have used HEADERS.
It looks like your app is using some (I guess) or static final or final field of some library class that does not exist in the profile of Java ME your mobile device implements.
But I can't figure out where that field comes from. Perhaps you should search your codebase for use of "HEADER" as an identifier ...
If the HEADER field is properly declared in your codebase (your MagiDEF interface) and the code you showed is using the HEADER from that interface, then you must have something wrong with your build or deployment process. Specifically, you are not deploying the version of MagiDEF that your code (above) has been compiled against. Maybe you've got an old version of something in some JAR file?
Basically, the error indicates that you have a binary incompatibility between some of the classes / interfaces that make up your app.

Categories