How to find the file passed to a Delphi app on Android? - android

We must write an Android app who knows how to open .xyz files.
However when we assign the .xyz files to our application, and after that we tap on an .xyz file in the Android's File Explorer, the application is properly started but the program doesn't see the file name as a parameter.
The code
ShowMessage(ParamStr(0)); //for debug...
ShowMessage(ParamStr(1));
Instead of showing in message boxes the application's full path and after this the full path of the tapped (clicked) file name it shows two empty strings.
How can we get the full path of the tapped (clicked) file?
UPDATE:
(A part of) The manifest looks like this:
<activity android:name="com.embarcadero.firemonkey.FMXNativeActivity"
android:label="MMBook"
android:configChanges="orientation|keyboardHidden">
<!-- Tell NativeActivity the name of our .so -->
<meta-data android:name="android.app.lib_name"
android:value="MMBook" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" android:host="*" android:pathPattern=".*\\.mma" android:mimeType="*/*" />
</intent-filter>
</activity>

You need to call SharedActivity.getIntent() to check if your app was started by an Intent or not. If a non-nil Intent is returned, you can retrieve its data (ie, the filename) and act accordingly. See my answer to the following question for an example:
Handling Custom URI in Delphi XE5 Android App
https://stackoverflow.com/a/20465775/65863

On Android, launching an activity and passing a file from a different app is implemented with Intents and Intent filters. (See Allowing Other Apps to Start Your Activity)
So usually your app must implement an Intent handler. In order to decide what action to take in your activity, you can read the Intent that was used to start it.
The URI of the selected file then can be retrieved with Intent.getData()
Java Example:
// Get the intent that started this activity
Intent intent = getIntent();
Uri data = intent.getData();
// Figure out what to do based on the intent type
if (intent.getType().indexOf("image/") != -1) {
// Handle intents with image data ...
} else if (intent.getType().equals("text/plain")) {
// Handle intents with text ...
}
See also: http://codeverge.com/embarcadero.delphi.firemonkey/android-intent-filter-associate/1057456

Related

How to make app appear as an option application?

What needs to be done to make your app appear as an option app.
For eg, when I select an image file, android shows me a list of applications to open the file with, like Gallery,Photos etc.
I want that android also shows my app in this list.
How to achieve this? I am unable to understand which android classes to use for it? Or do I need to modify manifest file to add some specific intents?
By defining intent filter you can achieve this. You can register your Android components via intent filters for certain events.If a component does not define one, it can only be called by explicit intents. The key for this registration is that your component registers for the correct action, mime-type and specifies the correct meta-data.
Eg.
<activity android:name=".BrowserActivitiy"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http"/>
</intent-filter>
</activity>
Above code will register an Activity for the Intent which is triggered when someone wants to open a webpage.
Source: http://www.vogella.com/tutorials/AndroidIntent/article.html

Handling Media Files in Android by installed apps

I have an app which records Audio and video. Then there is a list in the app which displays these recorded files. When user clicks on one of this file, I would like to display an option of apps that user can choose to play this clicked file. An example of it is shown below.
All the examples I have looked on internet is of using a media player which I am already doing but I would like the pause, stop etc function to be handled by an already available app in the users device.
Is this possible to do? If so how?
I guess your Activity which handles Audio and Video should have this in AndroidManifest.
The below intent-filer is for Audio files, similarly you can add for Video files for the same Activity.
<activity ...>
<intent-filter>
<action android:name="android.intent.action.GET_CONTENT" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.OPENABLE" />
<data android:mimeType="audio/*"/>
</intent-filter>
</activity>
EDIT:
For your Activity
Suppose you show a list of audio files and user is suppose to click one. So when the user clicks some item. You just need to set the result.
Ex.
setResult(RESULT_OK, new Intent().setData(YOUR_URI));
The 2nd param is just the data which we need to pass to the calling Application basically we pass the URI of the data.
EDIT 2: The RESULT_OK is inherited variable of Activity. You don't need to define it.
I hope it helps you.
I found the answer by readin up on the internet.
First prepare the file location and then open an intent with the data at this location
Uri fileURi = Uri.parse(tempFileURi); //i.e. /storage/emulated/0/Android/data/com.sahilsaid.appname/files/Music/Recording200.3gp
File file = new File(fileURi.toString());
if (file.exists()) {
Uri finalFileUri = Uri.fromFile(file);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(finalFileUri, URLConnection.guessContentTypeFromName(finalFileUri.toString()));
startActivity(intent);
}
You will also need to modify your AndroidManifest.xml file and add intent-filter as suggested above by #Aky
<activity
android:name=".exampleActivity"
android:label="#string/title_activity_example">
<intent-filter>
<action android:name="android.intent.action.GET_CONTENT" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.OPENABLE" />
<data android:mimeType="audio/*"/>
</intent-filter>
</activity>
For more info visit this article:
https://software.intel.com/en-us/blogs/2014/03/20/video-playing-with-android-media-player

How to make a android app that can be used as a default program for opening certain kind of link? [duplicate]

This question already has answers here:
How to implement my very own URI scheme on Android
(5 answers)
Closed 7 years ago.
I want to make an android app that can be used as a default application for opening a certain kind of link (like if I click http://facebook.com it will show me suggested app to open that link, browser or facebook's app)
These are called Implicit Intents
Assume you want to open your app on web link click with link "myApp://someapp"
then in your App Manifest
<activity android:name="MyActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myApp" android:host="path" />
</intent-filter>
</activity>
Whenever you click the above link, it will suggest to open your app.
If you want to developed application that allow the other application to complete the action using your application, for example in your case you want to handle the any of url user click, your application will be listed for complete the action. You have to create the activity that will handle the deep linking. For that you need to add some attributes to your handle activity in your android manifest. see below example
The following XML snippet shows how you might specify an intent filter in your manifest for deep linking. The URIs that start with “http”
<activity
android:name="com.example.android.BrowseActivity"
>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with "http://www.example.com/gizmos” -->
<data android:scheme="http"
android:host="www.example.com"
android:pathPrefix="/gizmos" />
<!-- note that the leading "/" is required for pathPrefix-->
<!-- Accepts URIs that begin with custom url "example://gizmos” -->
<data android:scheme="com.example.android"
android:host="gizmos" />
</intent-filter>
</activity>
Once you've added intent filters with URIs for activity content to your app manifest, Android is able to route any Intent that has matching URIs to your app at runtime.
Once the system starts your activity(BrowseActivity) through an intent filter, you can use data provided by the Intent to determine what you need to render. Call the getData() and getAction() methods to retrieve the data and action associated with the incoming Intent. You can call these methods at any time during the lifecycle of the activity, but you should generally do so during early callbacks such as onCreate() or onStart().
Here’s a snippet that shows how to retrieve data from an Intent inside BrowseActivity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = getIntent();
String action = intent.getAction();
Uri data = intent.getData();
}
Let me know if you need more help on this point thank you.

Launch Specific App when NFC is discovered

I am using NFC in my app and it is working fine. However I want to make sure that only my app is launched and no other App is there to handle the intent. Following is the code for it in my Manifest file:
<activity android:name="com.mypackage.name.BeamActivity">
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
I have another sample app on my phone which is detecting NFC Intent and providing me Intent Chooser. Following is the code for it in Manifest file.
<activity android:name="com.package2.name.NFCStickyNotesActivity" android:label="Sticky Notes" >
<!-- Handle notes detected from outside our application -->
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
I would like my App to be the only app to handle the particular NFC Intent when my App push it across from another device.
I am not sure whether I have to do something specific in the manifest file or in the code. Any help is appreciated.
The reason why you get an intent chooser is that multiple activities are registered for the data type text/plain. This is a rather common case and you should therefore avoid using such generic data types for the NDEF record that should launch your activity. You have two options to overcome this problem:
Use an NFC Forum external type for your NDEF record (this is what ThomasRS already mentioned). With this method you create a custom record type that is meaningful to your application only. You can create such a record (to write it to your tag or to send over Beam) with something like this:
NdefRecord extRecord = NdefRecord.createExternal(
"yourdomain.com", // your domain name
"yourtype", // your type name
textBytes); // payload
You can then register your activity to launch upon this record like this:
<activity ...>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="vnd.android.nfc" android:host="ext"
android:pathPrefix="/yourdomain.com:yourtype" />
</intent-filter>
</activity>
Use an Android Application Record (AAR). An AAR will make sure that the NDEF_DISCOVERED intent is delivered to an app with a specific package name only. You can create such a record (to write it to your tag or to send over Beam) with something like this:
NdefRecord appRecord = NdefRecord.createApplicationRecord(
"com.yourdomain.yourapp");
NdefRecord textRecord = NdefRecord.createTextRecord(
"en", // language code
"yourtext" // human-readable text);
NdefMessage msg = new NdefMessage(
textRecord,
appRecord); // use the AAR as the *last* record in your NDEF message
Use the External Type NDEF record with your own domain and give your app a corresponding intent-filter.

Custom actions using implicit intents between applications

I have been trying to get two activities in two separate applications to communicate using a custom action and an implicit intent.
The first application (server), has the following manifest:
<application android:icon="#drawable/ic_launcher"
android:label="#string/app_name" android:theme="#style/AppTheme">
<activity android:name="edu.example.sharing.manager.SecureFileShare"
android:label="#string/title_activity_secure_file_share" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="edu.example.sharing.action.STORE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
</application>
The second application creates an intent as follows:
File f = new File(s);
Uri fileUri = Uri.fromFile(f);
Intent intent = new Intent();
intent.setData(fileUri);
intent.setAction("edu.example.sharing.action.STORE");
startActivityForResult(intent, STORE_REQUEST);
Its manifest is normal. When I try to send the intent in the client application, however, I get an activity not found exception:
FATAL EXCEPTION: main
android.content.ActivityNotFoundException: No Activity found to handle Intent {act=edu.example.sharing.action.STORE dat=file:///storage/sdcard0/Download/Alarcon12-Rigoberto.pdf }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1545)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1416)
at android.app.Activity.startActivityForResult(Activity.java:3351)
at android.app.Activity.startActivityForResult(Activity.java:3312)
What's causing Android to not recognize the declared activity in the second application? Thanks.
After much looking, here's what I found:
When you use a built-in action type and attach a data field or when you use a custom action type with no data field, an intent-filter without a data element is ok.
However, when you define a custom action and include a data field, you must manually set the mime-type for the URI attached. The Android documentation claims that
Normally the type is inferred from the data itself. By setting this attribute, you disable that evaluation and force an explicit type.
But that's not the case. When I put in a file:// URI which ended in .txt, Android assigned it a null mime-type, so it wouldn't match any intent-filter, even one with a data and */* mime-type. I needed to manually set the intent's type using setDataAndType().
In short: You must manually define an intent's mime-type when using a custom action with data.
Firstly You can specify only which application to go to; you cant specify which avtivity to go to; I've already answered how to navigate to another app here; after that your control goes to the other app; you have to handle it there

Categories

Resources