If I have a content provider and CONTENT_URI in in application A, and it is also in the manifest. How do I call to it from application B?
Do I need to write the code in class that holds my sqlite database? Or do I need to make a whole new class and call to the provider from there?
Thanx in advance.
You may register Activity B to accept URIs according to their nature.
To do so, you add the following "intent-filer" section to Activity B in the AndroidManifest.xml
<activity android:name="ACTIVITY B PATH">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="THE MIME TYPE TO ACCEPT" />
</intent-filter>
</activity>
This will register Activity B to accept VIEW actions with URIs that math the MIME type.
Then, when Activity A runs the following code:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(CONTENT_URI));
activity.startActivity(intent);
Activity B will be activated automatically and you can read the URI by calling getIntent().getData() from your onCreate() method.
You may choose different ACTIONS (VIEW, EDIT, INSERT...) and DATA TYPES (MIME, SCHEMA, PATH...) that is most suitable to your needs.
Related
My app can save and load a custom type of files, let's say .foo.
My manifest tells this :
<activity
android:name=".activity.LoadActivity"
android:label="dummy">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" />
<data android:host="*" />
<data android:pathPattern=".*\\.foo" />
</intent-filter>
</activity>
With this, I can launch my activity when a browser try to open a .foo file.
But in my activity, onCreate() is called, but not onActivityResult(), how can I get the path to the file that get clicked ?
I've been searching the doc for a long time, cannot figure this out.
how can I get the path to the file that get clicked?
You can simply retrieve it from the incoming Intent. Just call:
Intent intent = getIntent();
intent.getData().toString();
To answer your whole question:
But in my activity, onCreate() is called, but not onActivityResult(), why ?
You can find the answer directly from the method Javadoc:
Called when an activity you launched exits [...]
This is not your case. onActivityResult is called only on activities that you launched (from your code). In the scenario that you're describing your activity is called from another application (the browser).
onActivityResult will be called after the ending of an activity you launched with method startActivityForResult
How can I get the file that led to my activity then ?
Call getIntent() in onCreate() to get the Intent that was used to start your activity. On there, getData() will return the Uri pointing to the file.
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
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
I'm running into a problem starting other activities from mine. I know this must be being done elsewhere as there are so many launcher apps out there which much use package manager to start specific activities...
I can get an Acitivity name I would like to start from the package manager, but how can I somehow parse this and turn it into an intent? Baring in mind I can't access the class... Also I would like to start that specific activity and not launch the MAIN intent from the package...
I'm sure someone must be doing this somewhere... It's kind of the point in activities isn't it?
Assuming you have following in your AndroidManifest.xml
<!-- The askUser dialog activity -->
<activity android:theme="#android:style/Theme.Dialog"
android:name="my.app.AskUserActivity"
android:excludeFromRecents="true"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="my.app.intents.AskUserConfirmConnect"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Then you can call this Activity by name, like this:
Intent dlgIntent = null;
dlgIntent = new Intent("my.app.intents.AskUserConfirmConnect");
dlgIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
dlgIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
context.startActivity(dlgIntent);
You can use setClassName(String, String) on the Intent to avoid needing the other class.
I have a widget that supposed to call an Activity of the main app when the user clicks on widget body. My setup works for a single widget instance but for a second instance of the same widget the PendingIntent gets reused and as result the vital information that I'm sending as extra gets overwritten for the 1st instance. So I figured that I should pass widget ID as Intent data however as soon as I add Intent#setData I would see in the log that 2 separate Intents are appropriately fired but the Activity fails to pick it up so basically Activity will not come up and nothing happens (no error or warning ether)
Here's how the activity is setup in the Manifest:
<activity android:name=".SearchResultsView"
android:label="#string/search_results"
<intent-filter>
<action android:name="bostone.android.search.RESULTS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
And here's code that is setup for handling the click
Intent di = new Intent("bostone.android.search.RESULTS");
di.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// if line below is commented out - the Activity will start
di.setData(ContentUris.withAppendedId(Uri.EMPTY, widgetId));
di.putExtra("URL", url);
views.setOnClickPendingIntent(R.id.widgetContent,
PendingIntent.getActivity(this, 0, di, 0));
The main app and the widget are packaged as 2 separate APK each in its own package and Manifest
I think you need a <data> tag in your <intent-filter> in order for the intent you are firing to match the intent-filter you have registered.
https://developer.android.com/guide/topics/manifest/data-element.html
Also using Uri.EMPTY may be a problem. I'd create your own Uri scheme, so that your setData() call looks something like:
di.setData(Uri.withAppendedPath(Uri.parse("droidln://widget/id/"), String.valueOf(appWidgetId)));
and your intent-filter would look like:
<intent-filter>
<action android:name="bostone.android.search.RESULTS" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="droidln"/>
</intent-filter>