Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Accessing an android device from within VFP

Status
Not open for further replies.

Doug Lindauer

Programmer
Feb 2, 2017
34
US
I need to be able to automate grabbing a binary file from my Android device from within VFP. In this case the device happens to be a Spektrum iX14 r/c transmitter and the binary file I want to grab is a telemetry file.

I can connect my Android device via USB and it shows up in Windows file explorer. But there doesn't seem to be a way for VFP to see it and copy any files over. I also tried running an app called webdav on the device. It lets you map the device via IP to a windows drive letter. It works over wifi, not usb. But even then VFP couldn't see the drive letter. I could call up a command window and then do a dos file copy to wherever but that is really clunky.

So can anyone shed some light on how I might be able to do this?
 
So here's my attempt to clean up Strongm's translation. I've also passed the code through Beautify (mainly to apply indentations and case conventions), but have not applied syntx colouring. I haven't tried to test it, so no guarantees.

Code:
 LOCAL ThisPC, objFolder, objShellAPP, objItem, myAndroid, AndroidFolder, myAndroidNameSpace

 myAndroid = "iX14" && Android device name, should be able to get this from Explorer
 ThisPC = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" && MyComputerFolder shell special folder,
 && i.e This Computer; do not change this

 objShellAPP = CREATEOBJECT("Shell.Application")
 objFolder = objShellAPP.Namespace(ThisPC)

 * Find my Android device
 FOR EACH objItem IN objFolder.Items
   IF objItem.NAME = myAndroid
     myAndroidNameSpace = objItem.PATH
   ENDIF
 NEXT

 * Now find my folder
 AndroidFolder = "\Internal shared storage"
 objFolder = objShellAPP.Namespace(myAndroidNameSpace + AndroidFolder)
 FOR EACH objItem IN objFolder.Items
   ? objItem.NAME, objItem.TYPE
 NEXT

 TARGET = objShellAPP.Namespace("e:\VFP9Projects\Weather\FlightStreams")
 * copies first item in the source folder to target
 * (if you want to copy a specific file you'll need to look through objFolder.Items to find it)
 TARGET.CopyHere(objFolder.Items.ITEM(0))

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Is the Android namespace delimiter likely to be forward slash to meet linux/unix conventions?

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.

There is no place like G28 X0 Y0 Z0
 
Is the Android namespace delimiter likely to be forward slash to meet linux/unix conventions?

Quite possible. I'm trying to test it now (after first forgetting to change the Android device name in Line 5). So far, it is causing VFP to crash.

I'm inclined not to pursue this, but to leave it to those who know more about this sort of thing than I do.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
>Is the Android namespace delimiter likely to be forward slash

No. The namespace is the Shell's namespace representation, and that follows Windows rules

> So far, it is causing VFP to crash
Really? I guess maybe FoxPro doesn't work well with all COM libraries, then. It's rock steady in VB(A)
I note some unexpected capitalisation of Path, Name, Type, Item and Target. I presume these are all reserved words in FoxPro.

>forgetting to change the Android device name in Line 5
Also, a different Android device may have a different root folder from "\Internal shared storage", for example on my phone it is "\internal storage"

>I'm inclined not to pursue this
Quitter! ;-)
 
I feel sure that the crashing of VFP is caused by some misunderstanding on my part, not in the code itself.

In general, VFP works well with COM libraries. As far as I remember - before it crashed - it was getting as far as the "Now find my folder" section, but some of the variables (myAndroidNameSpace ?) were not being set (they still had their default value, which is False).

Unexpected capitalisation: Yes, this was my mistake. They were caused by the Beautify tool I mentioned earlier. I should have fixed them manually. But this is unlikely to be causing problems. The words in question are key words (not reserved words), and it usually does no harm if they clash with PEMs of COM objects.

Root folder name: It is indeed "\Internal shared storage" in this case.

No,I'm not really a "quitter". I just prefer not to display my ignorance any more than I have already done.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
FWIW I did read in a thread on stackoverflow that the names inside shell32 are case sensitive. So perhaps objItem.NAME, objItem.TYPE should be objItem.Name, objItem.Type

(I've been spending all my time trying to understand how to use declare and things in the WinAPI. A lot to take in all at once.)

 
Hmm I'm not sure they are case sensitive.

This works, perhaps they are case sensitive at declaration, but not for usage?

Code:
FUNCTION BROWSER
	PARAMETER m.FILENAME,m.LINEPARAMS,m.TESTFILE
	LOCAL LNRETVAL, LCOPERATION
	PRIVATE m.FILENAME,m.LINEPARAMS,m.TESTFILE
	LCOPERATION = "Open"
	**
	DECLARE INTEGER ShellExecute IN SHELL32.DLL ;
		INTEGER handle,;
		STRING @sFile,;
		STRING @lp,;
		STRING @DIR,;
		STRING @dir1,;
		INTEGER ncmd
	**
	IF PCOUNT() < 3
		m.TESTFILE = .T.
	ENDIF
	IF PCOUNT() < 2
		m.LINEPARAMS = ""
	ENDIF
	IF m.TESTFILE
		IF MYFILE(m.FILENAME)
			LNRETVAL = SHELLEXECUTE(0, LCOPERATION, m.FILENAME, m.LINEPARAMS, "", 1)
		ELSE
			MESSAGEBOX("Unable to locate the File:"+m.FILENAME,48,"Problem")
		ENDIF
	ELSE
		LNRETVAL = SHELLEXECUTE(0, LCOPERATION, m.FILENAME, m.LINEPARAMS, "", 1)
	ENDIF
	CLEAR DLLS SHELLEXECUTE
	RETURN(.F.)

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.

There is no place like G28 X0 Y0 Z0
 
Success.

The capitalisation of the keywords was not an issue. I'm still not sure why it crashed before, but I noticed an error in the name of my target directory. Once I fixed that, it correctly displayed the names of all my Android folders, and it successfully copied the contents of the first folder (including a sub-folder) to the target directory.

Just to recap, the code that worked was the VFP code in my above post (posted at 15:22), but with the Android device name, the name of the Android root folder, and the name of the target directory, all amended as necessary.

So to go back to the original question, it should now be possible to copy any specific folder (test for its name in the second FOR EACH loop) and, once it is on your system, extract any specific file from that folder.

I feel encouraged to try to do that. But it's Friday evening and other thing are calling, so I'll leave the rest to others.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Ok, I stepped through with the debugger and changed a couple of things and it works! For me, this is incredibly HUGE! Here's my click event code. One of the subtle things that needed fixing was the copy command at the last line. It's a function so we needed to add parenthesis.

Code:
*-------------------------------------------------------------------------------
* FlightLog.cmdGETTELEMETRY.Click    && Get new telemetry file
*-------------------------------------------------------------------------------
    local ThisPC            ,; && standard windows GUID for the PC.  
          objShellAPP       ,; && 
          objFolder         ,; && 
          objItem           ,; && 
          myAndroid         ,; && 
          TelemetryFolder   ,; && folder where the iX14 writes telemetry files
          myAndroidNameSpace,; && folder, or path, to the Android device
          Target

    myAndroid  = "iX14" 
    ThisPC     = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}"     && Same for all computers
    objShellAPP= Createobject("Shell.Application")
    objFolder  = objShellAPP.Namespace(ThisPC)

    * Find my Android device folder and set the name space variable
    for each objItem in objFolder.Items
        if upper(objItem.Name) = upper(trim(myAndroid ))
            myAndroidNameSpace = objItem.Path 
        endif
    next
        
    * identify the specific folder where the telemetry files are written 
    TelemetryFolder = "\Internal shared storage\Download\AutoLog"     
    objFolder       = objShellAPP.Namespace(myAndroidNameSpace + TelemetryFolder)
    
    for each objItem in objFolder.Items   && list the folder contents for developmental testing
        ? objItem.Name, objItem.Type
    next
        
    * Copy files on Android to the destination folder
    Target = objShellAPP.Namespace("e:\VFP9Projects\Weather\FlightStreams")
    Target.CopyHere( objFolder.Items.Item(0)) && copies first item in the source folder to our target as test
 
Mike, Griff, and especially Strongm ... you guys are on my Christmas List. And I won't have to check it twice.
 
Works for me, too, but only rather slowly. Alone the step to discover the Android phone subfolder of "This PC". It will stay the same, so once you have it you could store the myAndroidNameSpace value for next time.

And it only works once I have set the usb setting for file transfer. And it resets to no file transfer all the time.

Having an ftp server app would make the phone available as long as that app runs. Also it gives you the security of a login to the ftp server and a way to limit access only to some specific subfolder, so I'd also look into that. But let me see if I find a decent Android 10/11 ftp server app that can run as background process on the phone.


Chriss
 
Very nice, but I would put an Exit command after myAndroidNameSpace is found. No need for further searching in that loop.

If the Android Phone is the only "Portable Device" connected you don't even need the name of the Android Phone.
You can look for objItem.type = "Portable Device"

Saving or storing myAndroidNameSpace's value for next time only helps if the Android device is not disconnected in between.
But even without saving or storing a consecutive run while still connected is just as fast.

A solution with Tiny Web Server app on the Android device running a webserver can let you download a file without the need of a cabled connection.
Use for instance URLDownloadToFile IN URLMON.DLL for downloading. That works. Tested in Android 9.

You can also have a look at the app File Manager (with big F in icon). Here you can setup a simple FTP server and download with the often used FTPGET.prg (tested that and it works and it also works in FileZilla)



 
Exit command is nice. I put one in the loop in my code. It will only save a few microseconds but it's neater.

I didn't want the user of the program to have to install anything on their device or go through any special steps so I didn't really consider using an FTP app. So far in my testing, the copying works really well and is fast enough to suit the purpose: which is to copy over the telemetry file. Now I'm working on understanding the layout of these binary files and how to work with them. Seems like I'll be relying on fopen/read/write/close but this is new territory for me. I did this kind of thing in a C++ course ... 15 years ago. So now I'm looking for my old class notes. :)
 
Hello Doug,

good, that it works for you. I can't say it works from the scratch, if I always have to go into settings and set the USB connection for file transfer, which isn't automatic. You started with invstigating about WebDAV, so I don't think the app free solution is a must have, as you started willing to use an extra app. If this is for customers, you would just better not need an app that has ads in it.

I can't recommmend the app Jack tried - File Manager (with big F in icon). It works, it can setup an FTP, the FileZilla FTP client I use can connect, but this app allows no safe connection. You have to run the app, choose "network access"and then this app goes into a screen showing you an ftp address and port, which you can use in a ftp client, or FTP code, VFP can do, starting as simple as using the shell FTP command. Or the internet trandsfer control OCX, which comes with VFP installation.

I'd look for something you can setup once and that starts with the device without appearing visually in the open apps.

Regarding reading in the file: You don't need your C++ course. All you need is VFPs FILETOSTR(), and you read the whole file into a string variable for further inspection. The nature of the file (text, binary) makes no difference, only that obviously a binary file will not only have readable text in it. It would pay to google for the file extension to find a format structure description, not just for which software this file is, but maybe you're also lucky and the data is stored in a human readable format. You can also use VFPs FOPEN, FREAD and FCLOSE, that could help to read it in smaller chunks, if the file is large.

And before you try in VFP, why not simply take a look into a file with notepad, or better yet notepad++? It might look all cryptic, then you know it needs more info to make something of of it, or only partly cryptic and partly readable, as is quite usual in binary files, too. There's no need to far that certain characters break an editor and cause a virus to escape. All 256 bytes in ASCII and in ANSI are not having any such effect, they only can look cryptic, but they don't execute anything.

To showcase how a file can both contain cryptic parts and text, open up any EXE you built with VFP. In the first few lines, the cryptic glyphs you see are also containing the sentence "This program cannot be run in DOS mode". And if you search for "<?xml" youll find the xml manifest embedded in any VFP9 exe, which an look like this (screenshot from notepad++):

embeddedxml_hohmp8.png


And that's not a rare exception of text embedded within an otherwise binary file. The notepad++ advantage here is, that it shows unprintible control characters with their short, like NUL is literally fo bytes that are 0. In notepad this part of the file looks like that:
embeddedxml2_jbyjz2.png


Well, what matters is the readable par looks the same.

In detail you can fail to see readable text because of byte alignment problems, but always, before starting to operate on files on a byte by byte basis, first take a glimpse with any editor, it doesn't even need to e a hex editor. There seems to be a fear about opening files with an editor, this is completely unnecessary. Even if you start editing it, unless you dont store that back, the file stays intact. And that's even unimportant when opening a copy.

If you care to have the hexeditor view, VFP has a hex editor within its HOME(): do Home()+"Tools\HexEdit\HexEdit":
hexedit_nu6nkh.png


You see less at once, the only advantage is it's easier to edit whil keeping the same file size, because it's not working as a normal editor in insert mode, where writing shifts existing text, you overwrite. And in case of VFP's Hexeditor you actually edit the hexadecmal values on the left, which even makes editing the readable text passages hard.

In short, Doug:

-I'm not convinced any of your customers will like this solution, I for one, would need to go into settings of my phone again and again, it's not connectiong for file transfer by default.
-You can simply try any text editor to look into the telemetry file and get an overview whether it's simply readable text or numbers, or fully binary.
-You should also gooogle a file structure known for the file extension. Unless it's a very genereic one like ".dat", that has many formats.


Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top