How to discover intent names within an existing Android application? (specifically Facebook) - android

I have a Samsung Galaxy Nexus Android phone and for whatever reason the Facebook app's menu UI is missing. This means I cannot get to the Settings screen. I figure I can start the intent from my own app, but how do I find the intent name? I've looked in the APK, but the manifest appears to be compiled into a binary format.
Does anyone know the intent name for the Facebook settings activity?
How can I get a list of the intents in an APK?
----------- Update -----------
The Facebook app's manifest includes:
<manifest android:versionCode="4130"
android:versionName="1.6.3"
package="com.facebook.katana"
xmlns:android="http://schemas.android.com/apk/res/android">
<activity android:label="#string/home_settings"
android:name=".SettingsActivity" />
I've got this in my code:
public void goToFacebookSettings(Context context) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setClassName("com.facebook.katana",
"com.facebook.katana.SettingsActivity");
context.startActivity(intent);
}
But this fails with:
FATAL EXCEPTION: main
java.lang.SecurityException: Permission Denial: starting Intent
{ act=android.intent.action.VIEW cmp=com.facebook.katana/.SettingsActivity }
Is this an inherent limitation, or can I comply with the security requirements in some way?

<activity android:label="#string/home_settings"
android:name=".SettingsActivity" />
This activity doesn't declare any intent-filters. It also doesn't have the android:exported attribute set to true. Which means it can only be launched by the Facebook app or an app that has the same user ID since it's considered for app-internal use only.
See the android:exported attribute documentation for more information.
Since this is for your personal use, you might be able to edit that attribute into the manifest and rebuild the application (also using apktool).

AFAIR you can use explicit activity invocation only inside of your apk - no way to call externally something that is not advertised.

Related

How to start an activity in an android Application from the Library

I have an Android application in Android Studio. And I've added a library into the application. The button, view, and activities are defined in the library. When I click on the button, I need to navigate to the activity defined in the application.
Usually, to navigate to another page, we used the intent, like this:
Intent intent = new Intent(MainActivity.this, Activity.class);
startActivity(intent);
But this is not a sufficient method to call the activity of the application from the library.
The problem is that the library and the application are independent; they have different packages. So the activity in the application cannot be recognized by the library.
How do I handle communication between the library and the application?
The normal way for doing this is to do this:
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.my.package","com.my.package.activity.ActivityName");
startActivity(intent);
This is an explicit reference to an activity within your library. You should ensure that when starting this Activity that you catch the ActivityNotFoundException as this can happen when the Activity does not exist in the system.
Ideally when building this Intent you should insure that you can resolve it by using PackageManager APIs.
However you should try to avoid hardcoding packages, but when it comes to a library, sometimes you don't have a choice.
Also one thing to note is that within the library you need to ensure that the Activity is exported so that you can access it outside of your application.
android:exported
Whether or not the activity can be launched by
components of other applications — "true" if it can be, and "false" if
not. If "false", the activity can be launched only by components of
the same application or applications with the same user ID. The
default value depends on whether the activity contains intent filters.
The absence of any filters means that the activity can be invoked only
by specifying its exact class name. This implies that the activity is
intended only for application-internal use (since others would not
know the class name). So in this case, the default value is "false".
On the other hand, the presence of at least one filter implies that
the activity is intended for external use, so the default value is
"true".
This attribute is not the only way to limit an activity's exposure to
other applications. You can also use a permission to limit the
external entities that can invoke the activity (see the permission
attribute).
Ref
http://developer.android.com/guide/topics/manifest/activity-element.html
Include the activity in AndroidManifest.xml.
To access an activity from any other project the easiest way is to
pass the whole class name (including package, e.g;
"com.myproject.MainActivitiy")
Calling from your library :
Intent intent= new Intent("com.myproject.MainActivitiy");
startActivity(intent);
And in your project manifest declare it like this
<activity
android:name="com.myproject.MainActivitiy"
android:label="#string/app_name" >
<intent-filter>
<action android:name="com.myproject.MainActivitiy" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
In this case, Intent can be used by providing the full class name including the package.
Let us suppose your current Activity class is MainActivity.java with package name com.app.myproject.
And you want to navigate to another Activity with class named Activity.java that is in another package com.app.external.
Include com.app.external.Activity.java in the manifest of your current project/library.
<activity
android:name="com.app.external.Activity"
android:label="#string/title_activity_login"
android:screenOrientation="portrait">
</activity>
And your Intent should be like this -
Intent intent = new Intent(MainActivity.this, com.app.external.Activity.class);
startActivity(intent);
In this case use Implicit Intent
Inside library Activity TESTActivity :
Intent intent = new Intent();
intent.setAction("com.myapp.myimplicit_action");
startActivity(intent);
and here is my manifest file declaration for some activity say 'ImplicitActivity' with the same action
<activity android:name=".ImplicitActivity">
<intent-filter>
<action android:name="com.myapp.myimplicit_action" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

Not the right Activity java.lang.SecurityException: Permission Denial: starting Intent

I read all other answers about this problem but it doesn't help me.
I have an app (MyApp) which include a library (named lib (example)). In my app, I call LoginActivity in my lib.
But I have this exception.
java.lang.SecurityException: Permission Denial: starting Intent { cmp=fr.myotherapp/.activity.LoginActivity
Myotherapp is a other app which I created and installed in the same device.
I don't set "exported"="true" in myotherapp manifest because I dont want to use this one but I set "exported"="true" for the activity in the lib manifest.
I use Android Studio.
Why does Android want to use this one even if I call the activity like this ?
final Intent intent = new Intent(mContext, fr.lib.activity.LoginActivity.class);
Thanks
If you are using eclipse, try adding manifestmerger.enabled=true to your project.properties file.
relevant docs :
http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger#TOC-Android-Manifest-file-merging
https://roostertech.wordpress.com/2013/10/29/manifest-merger/

Android Service in a library not being updated when shared by two applications

I've got two separate applications that use a common background service (which is in a common library which both applications include) to collect Bluetooth data. Everything works fine on first installation of the applications.
The problem is that when one of the applications is re-deployed after having the common service changed, it still uses the service previously installed.
Here's some info and an example to clarify things:
The 2 applications are named BioSound, and BioZen. Each of them includes a common library called AndroidSpineServerLib, which in terns includes the common library AndroidBTService (which contains the background service)
For example, on first installation AndroidBTService has a version number of, say 1.0. When the applications are deployed everything is fine, Both BioZen and BioSound uses the V1.0 service.
Then I make a change to BioSound, and AndroidBTService, incrementing it's version to V1.1. When I deploy BioSound after this I would expect it to use the newly changed service V1.1, but it continues to use the V1.0 service. The only way to fix this is to remove the BioZen , then BioSound the correct service ( I don't even have to reinstall BioSound).
Programatically, when I start each application I bind to the service, and when each application exits I unbind the service.
Obviously I'm missing something but can't figure it out. Any ideas?
Your problem may be that you are using an implicit intent to communicate with your service that doesn't specific an application, only an action. That intent (which you're using in both applications) ends up getting resolved to one particular application's service. Instead, make sure to specify the explicit intent with the particular component or class. See the Intent docs for details.
I'm sure this is it but I'm having difficulty with the details.
Here's the existing code:
Mainfest for the main Application:
<application android:icon="#drawable/biosound_icon" android:label="#string/app_name" android:debuggable="true">
<service
android:name="com.t2.biofeedback.BioFeedbackService">
<intent-filter>
<action android:name="com.t2.biofeedback.IBioFeedbackService"/>
</intent-filter>
</service>
</application>
The call to bind the service was in the library AndroidSpineServerLib
Intent intent2 = new Intent("com.t2.biofeedback.IBioFeedbackService");
bindService(intent2, mConnection, Context.BIND_AUTO_CREATE);
So I can see how the service was bound to a specific application
To fix this I tried:
Intent intent2 = new Intent(this, BioFeedbackService.class);
bindService(intent2, mConnection, Context.BIND_AUTO_CREATE);
The problem is that the service was not created.
I also tried the following
In the manifest of the service:
<service
android:class=".service.BioFeedbackService">
<intent-filter>
<action android:name="com.t2.biofeedback.IBioFeedbackService"/>
</intent-filter>
</service>
And in the library where I bind the service:
Intent intent2 = new Intent();
intent2.setAction("com.t2.biofeedback.IBioFeedbackService");
bindService(intent2, mConnection, Context.BIND_AUTO_CREATE);
Still no luck.
Maybe I'm putting the service definition in the wrong manifest.
Remember I have the following hierarchy
Main Application references:
AndroidBTService (Library), which references
AndroidSpineServerLib (Library)
So I have 3 manifests and not sure which to update.

Changing launcher Activity name in a new application version

I have developed a new release of an application and I have changed the name of the activity which is launched.
Before the upgrade, in the manifest was:
<activity
android:name=".Splash"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:theme="#android:style/Theme.NoTitleBar" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
and then I only changed the name and the package of the activity and now it is:
<activity
android:name=".view.SplashActivity"
... >
...
</activity>
what happens is that after people download the application from the market, the launcher is not refreshing and it still calls to the old path to the activity.
Do you know how to solve this?
Refer Things That Cannot Change
It says,
A subtle but important aspect of what constitutes a break in compatibility is the android:name attribute of your activity, service, and receiver components. This can be surprising because we think of android:name as pointing to the private code implementing our application, but it is also (in combination with the manifest package name) the official unique public name for that component, as represented by the ComponentName class.
Changing the component name inside of an application can have negative consequences for your users. Some examples are:
If the name of a main activity of your application is changed, any shortcuts the user made to it will no longer work. A shortcut is an Intent that directly specifies the ComponentName it should run.
If the name of a service implementing a Live Wallpaper changes, then a user who has enabled your Live Wallpaper will have their wallpaper revert to the system default when getting the new version of your app. The same is true for Input Methods, Accessibility Services, Honeycomb’s new advanced Widgets, and so on.
If the name of a receiver implementing a Device Admin changes, then as with the live wallpaper example, the device admin will be disabled when the application is updated. This also applies to other kinds of receivers, such as App Widgets.
So if possible, don't change the name of components declared in the manifest, or remove any icon pointing to that component using below code.
ComponentName componentToDisable = new ComponentName("application.package.name", "packagename.ActivityClassName");
getPackageManager().setComponentEnabledSetting(componentToDisable, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
Also specify new launcher activity in manifest using <intent-filter>...</intent-filter> so that your new activity will be launched when user clicks launcher icon.
Does the activity is called correctly if you start the activity in debug mode on your phone.
If so check if you did something of the following:
you changed the whole package name
you signed it not at all or not correctly
Also you might check out http://developer.android.com/guide/publishing/publishing_overview.html
Anyway. If the application runs correctly on your debugging phone there is something wrong with your publishing parameters and you should go through the page above step by step.
If not you might check the path values, like package and name of the activity and the filters.

How do I start an Activity from a Service?

So I've been searching around for a week or so, and it appears to be quite possible to start an Activity from a Service, the general order of things going like this:
Intent myIntent = new Intent();
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
myIntent.setComponent(new ComponentName("[package]", "[class]"));
getApplication().startActivity(myIntent);
When trying this from a WallpaperService, I'm getting what appears to be a wallpaper-specific error requires android.permission.BIND_WALLPAPER. Stack trace shows the startActivity as the culprit.
I have no idea how to give it this permission; I have tried putting android:permission="android.permission.BIND_WALLPAPER" on every tag in the manifest that'll take it, as well as <uses-permission android:name="android.permission.BIND_WALLPAPER" />
Notably, the debug view does have the warning:
WARN/PackageManager(59): Not granting permission
android.permission.BIND_WALLPAPER to package (protectionLevel=3
flags=0xbe46)
General question being asked is in the title.
Thanks in advance!
You want to put android:permission="android.permission.BIND_WALLPAPER" inside only the service tag and nowhere else.

Categories

Resources