App intents in Android - android

I need to launch an app from the command line with
am start com.project.app
but it says unable to resolve intent.
I understand that I need to supply the intent, but I don't know what the intent is. I just want to start the app. Is there any way I can list the intents that the app has, find out what the intent was for an app already started, or find out the intent from a shortcut on the home screen?
Thanks.

To start an activity of any package, you need to provide the component name of that package.
It is something like /. or defined in the AndroidManifest.xml
for example, Package name: com.me.test and Activity name is com.me.test.app.TestActivity. Then you need to write
am start -n com.me.test/.app.TestActivity

Related

Why do we get these "invalid" intents?

We have an app with an Activity that can be started in two ways:
From another Activity - always with some extra data filled in
From deep linking
As far as I can see this is always working just fine. We either get the Intent.ACTION_VIEW with a data URI, or we get some string extras.
However, we have a very few instances where action is Intent.ACTION_MAIN and there are no extra data.
The toString() of the Intent is as follows (class name changed):
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10400000 cmp=com.example.OurActivity }
Intent.getExtras() returns null, Intent.getDataString() returns null.
In which cases can this happen? Why is the category for the Activity Intent.CATEGORY_LAUNCHER? How can we get the data needed to show the user the right contents?
launchMode is not specified for the Activity. The only IntentFilter in AndroidManifest.xml is for the deep linking (and not the launcher category).
The issue happens on Android 4-6 on a wide range of devices.
Edit: Forgot to mention the flags:
As the print out suggests the flags for the Intent are FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_BROUGHT_TO_FRONT. I suppose that could be relevant here.
I believe, I nailed it:
There're launchers, like Nova Launcher which allows users to start with any of app's Activities, instead of the normal flow:
For example, you can add a shortcut on your desktop to start Gmail client with Account setup Activity.
And in this case, Activity is being started with empty Extras and technically it becomes a launcher's Activity.
Now that AndroidManifest.xml is manipulated by the build system, it often happens that libraries that you include also add things to the manifest, which I suspect may be happening here.
Although you state that there is only one IntentFilter in the manifest, have you actually checked the installed app to see what its manifest says (rather than relying on what you think you put in your source code)?
Various apps are available in the Play Store to show you the manifest of an installed app - including App Detective (which I wrote).

Can an app start a component in another app through explicit intent?

Can App A start a component in App B through explicit intent?
I understand that general use of an explicit intent is to start a component within the same app. Implicit intents are used to cross process boundary.
Scenario:
App B defines and uses a custom permission "foo"
App A uses
PackageManager API to identify App B (app which defined "foo")
Can App A start a component within App B through explicit intent?
I don't think this is possible because explicit intent needs- app package and component name.
if (PackageManager.PERMISSION_GRANTED == packageManager
.checkPermission("foo",
pk.packageName))
results.add("package name: "+pk.applicationInfo.packageName+ " class name:
"+pk.applicationInfo.classNa);
}
Class name is null. So, per my understanding there is no way inter-app communication is possible through explicit intent just by relying on PackageManager APIs. In Android 5, you can call AIDL Services only through explicit intent but at dev-time the caller needs to know package and component name of app exposing the AIDL. Is my understanding correct?
Can App A start a component within App B?
App A can try. Whether App A will succeed depends on several things, including whether the component is exported and whether the component is secured by a permission.
I don't think this is possible because explicit intent needs- app package and component name.
The application ID and component name are both strings. Apps can use strings. Correctly getting the application ID and component name may take some work, depending upon the relationship between App A and App B.
As a counter-example, the only way to bind to a service on Android 5.0+ is via an explicit Intent. Hence, if App A wishes to bind to a service exported by App B, App A has no choice but to create an explicit Intent.
No way. If you want to start something that's outside your app you have to declare a implicit intent. Otherwise android will look for it inside your package, probably not gonna find anything and crash.
From the docs:
You'll typically use an explicit intent to start a component in your
own app, because you know the class name of the activity or service
you want to start.
Under "Intent Types" - http://developer.android.com/guide/components/intents-filters.html
So, typically you will not... but you can do this however it is not straightforward. To create a proper explicit intent, you will need the application context and the class.
To get the context of another application:
createPackageContext (String packageName, int flags)
http://developer.android.com/reference/android/content/Context.html#createPackageContext(java.lang.String,%20int)
For the class, you can request 'Activity' and 'Service' classes from package manager. You could also try to use reflection. You can also use the fully qualified string name of the package and assume it is correct and/or will not change. If you want, you can include a stub of the class in your app, thereby obtaining a reference to it (if you have access to the source or a stub library).
If there are permission restrictions, you will need to request permission.

Android start service of an app from another android app

I have two applications installed on the device: from one app I want to start a service as follows:
Intent i = new Intent();
i.setComponent(new ComponentName("com.app.service", "com.app.service.NotificationService"));
context.startService(i);
The second app is only installed but not started.
What I want is to start the notification service(which should create a notification) from the second service by using the above code.
In the manifest file of the second app I declare the service as follows:
<service
android:name=".service.NotificationService"
android:exported="true" />
The problem is that the Notification Service from the second app does not start.
Any ideas on why this happens?
Just to be clear, the second app is the Notifications one right?
If so, what I would try is loading both apps individually first, and then creating a method in your second one to access the information from the first one.
I had a similar scenario, let me just find the solution (somewhere on my laptop) and get back to you more specifically.
Not exactly a great solution but I have fixed my problem by removing the NotificationService file from the com.app.service directory, and adding it to the com.app directory.
This fixed the issue for me, meaning that I managed to start the service of the second application from the first application.

Pasing data through app after install without launching

Refering to this post I need to ask something else.
I have an application "A" which download and install another app "B".
I want B to "transfer" data to A and then A will use this data to do work.
I know that we can transfer data with intent.
After installing B app with A, Android provide a choice with "Ok" or "Launch" ; my question is :
Is that possible to pass data from B to A when we click on "Ok"? (So we stay in A app without launching B)
If yes, how? Is that possible to "invisible" launch B? How should I code B to get this comportement?
I know that might be hard to understand, you can try to check my previous draw (here again).
EDIT:
I use this code to launch B installation from A.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri uri = Uri.fromFile(new File(Environment.getExternalStorageDirectory().toString() + "/downloadedfile.apk"));
Intent.setDataAndType(uri, "application/vnd.android.package-archive");
getApplicationContext().startActivity(intent);
There are many ways to handle this, here is one that (I believe) is quite simple to implement. Since your A app [presumably] knows what it is installing:
App A: Add a BroadcastReceiver to react to the installation, though by default it is off.
Android: BroadcastReceiver on application install / uninstall
App B: Add a Service for background communication.
Note: A Service must be exported to be accessible to other apps via explicit intent, but this creates a security concern, as it is open to all other apps.
When a user of App A clicks to install App B:
Start the BroadcastReceiver with a filter set to detect the install:
stackoverflow...android-broadcastreceiver-on-application-install-uninstall
App A starts the install.
When the BroadcastReceiver detects the package has been added (the package name will be in the received intent,) it can stop the BroadcastReceiver, and can send an explicit Intent naming the Service in AppB. You can pass whatever data you need in the intent.
When the AppB service receives the intent, it can act in any way you'd like.
Service is always created using a non-null Intent, though the 'action' of explicit Intents is null.
Service.onStartCommand() might receive a null Intent if the service was re-created.
I'd fill in more of the code, but I have a day job ;)
Note:
Intent.ACTION_PACKAGE_ADDED called when a package is installed.
Intent.ACTION_PACKAGE_INSTALL was never used, and was deprecated in API 14.
http://developer.android.com/reference/android/content/BroadcastReceiver.html
http://developer.android.com/reference/android/content/Intent.html

Launch Android app from browser, when app doesn't have an intent filter defined

I know how to open an app that has an intent filter defined, as answered in Launch custom android application from android browser, but what if I'm not in control of the Android app, and it hasn't already defined an intent filter I can use?
Do I need to contact the developer and ask to add an intent filter, or is there some other way to open the application from a browser?
If the app's Activity does not have an IntentFilter defined, by default the system will keep the Activity private and not export it for other apps to start it. However, if the developer has set the android:exported="true" for that Activity in the app's manifest you should be able to start it by specifying just the component name in the Intent.

Categories

Resources