Profile cover photo
Profile photo
Nirav Kaku
80 followers
80 followers
About
Nirav Kaku's posts

Delphi + Android - Get the file path of image / video selected from media browser - Solved !!

Hi guys, after a full day of research (I know... I was slow!), I have find wrote the code that can open the media gallery and return the file path (along with all other information) of the media file selected. Hope this helps!

<code>

uses
...
Androidapi.JNI.GraphicsContentViewText,
Androidapi.JNI.Net,
Androidapi.Helpers,
FMX.Platform.Android,
FMX.Platform,
Androidapi.JNIBridge,
Androidapi.JNI.JavaTypes,
....

//open the gallery
procedure TForm2.Button1Click(Sender: TObject);
var
Data : Jnet_Uri;
Intent : JIntent;
begin
FMessageSubscriptionID := TMessageManager.DefaultManager.SubscribeToMessage(TMessageResultNotification,
HandleActivityMessage);
Intent := TJIntent.Create;
Intent.setType(StringToJString('image/* video/*'));

Intent.setAction(TJIntent.JavaClass.ACTION_GET_CONTENT);
MainActivity.startActivityForResult(Intent, 0);
end;

// when message is received
procedure TForm2.HandleActivityMessage(const Sender: TObject;
const M: TMessage);
begin
if M is TMessageResultNotification then
HandleIntentAction(TMessageReceivedNotification(M).Value);
end;

// code to get the details of the file selected from gallery
function TForm2.HandleIntentAction(const Data: JIntent): Boolean;
var
P: TJavaObjectArray<JString>; // incase you want only specific fields... not used here. I have passed nil to get all the columns.
C: JCursor;
I: Integer;
begin
Memo1.Lines.Text := JStringToString(Data.getData.toString); // this returns the URI in string perfectly... so I know that I am getting the file path properly

// this is suppose to give the information back to C ( : JCursor)
C := MainActivity.getContentResolver.query(
Data.getData,
nil, // when projection is nil... it returns all columns. Ideally, you should only ask for the columns you need
StringToJString(''), // java accepts nuil... but you cannot give nil here, you need to give an empty JString
nil,
StringToJString('')); // java accepts nuil... but you cannot give nil here, you need to give an empty JString

C.moveToFirst;

Memo1.Lines.Add('Path:' + JStringToString(Data.getData.getPath));
Memo1.Lines.Add('No of columns returned:' + C.getColumnCount.ToString);

for I := 0 to C.getColumnCount - 1 do
begin
if JStringToString(C.getColumnName(I)) = '_data' then // '_data' column contains the path... you can use this to create the filestream to upload or do whatever....
Edit1.Text := JStringToString(C.getString(I));

// column name : column value formatted string
Memo1.Lines.Add(JStringToString(C.getColumnName(I)) +': ' + JStringToString(C.getString(I)));
end;
end;

</code>



Android question...

This might sound ridiculously simple to do but cross platform API isn't my strong point.

I started an Activity with the Intent of consuming content from the Gallery which works fine. However, the Intent returns the URI of the file (as content://storage/... /media/12345) instead of the actual file path.

I was expecting something like '/storage/emulated/0/.../VID_18161918.MP4'

Any pointers?

UPDATE ----
after going through the Android documentation and some examples (that probably work in Java). This is the code which I 'feel' should work.. but it is not... any help would be great

<code>
function TForm2.HandleIntentAction(const Data: JIntent): Boolean;
var
P: TJavaObjectArray<JString>;
C: JCursor;
I: Integer;

begin
Memo1.Lines.Text := JStringToString(Data.getData.toString); // this returns the URI in string perfectly... so I know that I am getting the file path properly


// this is to prepare the information I need... they call it projection
P := TJavaObjectArray<JString>.Create(2);
P.Items[1] := StringToJString('_ID');
P.Items[2] := StringToJString('DATA');

// this is suppose to give the information back to C ( : JCursor)
C := MainActivity.getContentResolver.query(Data.getData, P, nil, nil, nil);
C.moveToFirst;

I := 0;
repeat
Memo1.Lines.Add(JStringToString(C.getString(I))); // unforturnately... nothing comes here --- so I am guessing I am doing something wrong in creating the projection or calling the ContentResolver (??)

Inc(I);
until (C.isLast);


end;
</code>

Post has attachment
Google Drive - Some basic functionality - Solved Code attached

Hey guys, I have acheived a few solutions to uploading files from device to GDrive and I am posting the functions here for anyone to use. It's not 100% refined but it willl get the job done (at least it did for me!)

With this code you can...

1. Upload a file
2. Rename a file
3. Move a file between folders
4. Create a folder
5. Rename a folder
6. Move folders between folders

I am attaching the link to the file, you can download it.

https://www.dropbox.com/s/2hvourc648hz5bb/GDrive_ForCommunity.rar?dl=0

PS::
You will need to put in your Google credentials (ClientID , Client Secret) to get the Auth Token which you can use to get the Access Token. Once that's done, this, code should work. Also, you will need your gdrive accounts root folder id.

It supports the latest Google Drive API version - v3.


HTH
Nirav


Guys, I am at my wits end!! Please help... I am executing an API via Google... and it works perfectly (moving folders into another folder)... however, the same call via my Delphi code will not work! Through Delphi, I can create the folders , I can rename them... but I cannot change their parents! I am doing exactly what it's asking me to do!

Here's the code....

RESTResponseDatasetAdapter1.AutoUpdate := false;
RESTRequest1.Params.Clear;
RESTRequest1.ClearBody;
RESTRequest1.Method:= rmPATCH;
RESTClient1.BaseURL := 'https://content.googleapis.com/drive/v3/files/'+edtMOveFolderSource.Text;

Folder := TJSONObject.Create;
Folder.AddPair(TJSONPair.Create('addParents', edtMoveFolderDest.Text));
rsr1.AddBody(Folder);

try
RESTResponse1.Execute;
Memo1.Text := rsp1.Content;
except
on e: Exception do
ShowMessage(e.Message);
end;

ps:
I have got authentication done.... and I can create a new folder , rename the folder and even upload the file (to the root). But this API gives me the right result. But it doesn't do anything.

However, from the google API site, the same function work... in the Try It sectoin. But when I do the same from Delphi, it wont work. :-( I have the Raw https call (from Firefox) so I am guessing, that I am screwing up some place in creating the request (not one my strenghts) :-)

Hey guys,

I am trying to figure out a way where I can PUSH data from my Delphi Websocket server to client (which is a browser) without client invokation. I know Andre Mussche had done some work on this but I cant find a sample where the clietn is a browser (not a Delphi executable).

Any help would be great!

Hey guys,

Anyone here thinking of writing helper functions for TMapView? I feel the current component has many limitations and can use some additional functionality... for example...

TMapView.StartNavigation(Dest: string) or

TMapView.GetLatLong(ScreenPixelX, ScreenPixelY): TMapCoordinate

...so on and so forth.


Callout to all Delphi Android programmers....

Is there a guide on how to use Android classes in Delphi? I have gone through Brian Long's coderage video but I was wondering if there was something a bit more detailed than that...

I am trying to use Google maps directly (intead of TMapView)

Hey guys,

TMapView on Android query...

Anyone has a solution to figure out screen coordinates to lat long ?

I need a function on which I will supply the map component's X,Y pixel point and it returns the LatLong for that pixel.

Happy Birthday +Alister Christie​

Android Background Services

Here's a weird problem...

I have created a sticky service which gets started from my app. The services spawns a separate thread that calls a URL after every 10 seconds. That's it.

What I am expecting is that the service keeps running even if I close my app... That the url should be called every 10 seconds. But when I close my app... The service stops functioning. When I start the app... The service works well.

Are not services required to run regardless? What am I doing / expecting wrong?

Wait while more posts are being loaded