Show system settings fragment/activity inside your own app - android

I need to display application settings screen for a specific system application in my own Android app. Currently I can only launch it as a separate activity and on a timer in the background I check if user performed the action (Force stop) and then re-lauch my activity.
What I have now:
public static void showInstalledAppDetails(Context context, String packageName)
{
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", packageName, null);
intent.setData(uri);
context.startActivity(intent);
}
I would like to integrate the settings screen into my own application, I have tried using ActivityGroup and then launching system settings as child activity. The operation fails with Security Exception (lack of MANAGE_USB permission).
Is there a way to make this work?
Thanks, Swav

Is there a way to make this work?
No, sorry. You cannot combine multiple activities from disparate processes into a single UI.

Related

getExtras() return null on Application level (-class)

On my Application level I receive null for getExtras(), but on Activity level i can see them correctly.
public class MyApplication extends Application
{
#Override
public void onCreate() {
super.onCreate();
Intent intent = getPackageManager().getLaunchIntentForPackage("com.example.MyApp");
if (intent != null){
String mStaticWorldUrl = intent.getStringExtra("arg1Name");
String mStaticWorldIconUrl = intent.getStringExtra("arg2Name");
Log.i("LOG", mStaticWorldUrl + " --- " + mStaticWorldIconUrl);
}
}
}
I'm calling the app from some shortcuts that were created by this code:
(- each shortcut has different Extras sent to the Intent)
// create a shortcut for the specific app
public static void createShortcutForPackage(Context context,
String packageName, String className, String shortcutName,
String arg1Name, String arg1Val, String arg2Name, String arg2Val,
int iconID) {
Intent intent = new Intent();
intent.setComponent(new ComponentName(packageName, className));
PackageManager pm = context.getPackageManager();
Context pkgContext = createPackageContext(context, packageName);
if (pkgContext == null)
return;
Intent shortcut = new Intent("com.android.launcher.action.INSTALL_SHORTCUT");
Intent shortcutIntent = pm.getLaunchIntentForPackage(packageName);
if (arg1Name != null)
shortcutIntent.putExtra(arg1Name, arg1Val);
if (arg2Name != null)
shortcutIntent.putExtra(arg2Name, arg2Val);
shortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, shortcutName);
shortcut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,Intent.ShortcutIconResource.fromContext(context, iconID));
shortcut.putExtra("duplicate", false);
context.sendBroadcast(shortcut);
}
how can I read these Extras on the Application level?
or is there any other way to create different shortcuts for application and read its' "parameters" data on Application?
The Application class is static for the application: there is only ever a single instance of it for your app's process. If your app has been launched with a normal launch Intent, rather than a shortcut you created, then no extras would be present. The app process does not die when HOME or BACK is pressed, so the Intent used to launch the package may not be what you think it should be.
You should not need to look at the Intent at the Application level. Intent objects are not intended to be "sent" there, but rather to an Activity, Service or BroadcastReceiver.
This is conceptual error which facing to get data in application class using getExtra which is the method of Intent
Reason for this issue:
No extras is because the queried intent was one that was generated
one line earlier, it is the intent that the OS has generated for the
package as requested in the following code: Intent intent =
getPackageManager().getLaunchIntentForPackage("com.example.M‌​yApp");
Intent objects within an Application class instance: they are not
delivered there
Let's understand following things to use in upcoming usage while anyone want to get data in application level
What is Intent ?
What is the Use of Intent?
What other things can we use to achieve this?
What is Intent?
An Intent provides a facility for performing Late runtime binding between the code in different applications . Its most significant use is in the launching of activities, where it can be thought of as the glue between activities. It is basically a passive data structure holding an abstract description of an action to be performed.
extras - This is a Bundle of any additional information. This can be used to provide extended information to the component. For example, if we have a action to send an e-mail message, we could also include extra pieces of data here to supply a subject, body, etc.
What is the Use of Intent?
Use to intents facilitate communication between components in several ways, Followings are standard use
To start an activity.
To start a service.
To deliver a broadcast
What other things can we use to achieve this?
There are lots of things we can use to achive this and solved this
issue.
But right now here i mentioned only one which is standard and secured
to use application
Content provider: To offer a file from your app to another app is to
send the receiving app the file's content URI and grant temporary
access permissions to that URI. Content URIs with temporary URI
access permissions are secure because they apply only to the app that
receives the URI, and they expire automatically.

Launch an activity of an application from a different application on Android

I need to launch an activity (not the main activity) of an application from an application I have made. The activity I want to launch is proprietary, hence, I cannot make any changes to its code(or manifest).
For example: I want to launch somebody's Facebook profile from my own application. A normal intent to facebook from my app would open the 'newsfeed'(which I don't want). I want to know how to access any other activity.
Thanks in advance!
The little code I have:
String PACKAGE="com.facebook.katana";
Intent launchIntent = getPackageManager()
.getLaunchIntentForPackage(PACKAGE);
startActivity(launchIntent);
To launch specific activity you need to use explicit intent. Or use implicit intent with action if you know what action that activity answers to.
To use explicit intent you can do the following (provided you call it from the activity):
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.package.name", "com.package.name.ActivityName"));
if(getPackageManager().resolveActivity(intent, 0) != null) {
startActivity(intent);
} else {
Toast.makeText(this, "No app installed that can perform this action", Toast.LENGTH_SHORT).show();
}
You can also add flags to the intent, add actions and categories. As long as the intent can be resolved as viable intent by the PackageManager, it will launch the activity.
Now...
The question about facebook profile, is a different one.
Perhaps, the best way to achieve that would be to use intent with action VIEW and povide Intent.setData with uri to the profile page. That should also be checked for possibility of being resolved correctly. And then will launch the chooser of all supported activities to open it, which should include facebook application. It is then up to user to open the intent using Facebook app or launcher.

Test activity from another task

I am trying to test my activity which has a button to go to a People application with ActivityInstrumentationTestCase2. But the problem is People application starts edit activity in another task, and clearly I don't have access there. So, what to do? How to send signals to People application?
My intent is:
Intent intent = new Intent(Intent.ACTION_INSERT);
intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
intent.putExtra(ContactsContract.Intents.Insert.NAME, "");
intent.putExtra(ContactsContract.Intents.Insert.PHONE, "");
Well, I figured it out, pretty sure other developers will find it useful.
First of all, to enable testing interaction with People application you can prefill the contact data with related Intent fields:
public static void addAsContactConfirmed(final Context context, final Person person) {
Intent intent = new Intent(Intent.ACTION_INSERT);
intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
intent.putExtra(ContactsContract.Intents.Insert.NAME, person.name);
intent.putExtra(ContactsContract.Intents.Insert.PHONE, person.mobile);
intent.putExtra(ContactsContract.Intents.Insert.EMAIL, person.email);
intent.putExtra("finishActivityOnSaveCompleted", true); // this line enables instant return People to our app
context.startActivity(intent);
}
Then you need to press back button, and this is the tricky part:
You can't just finish(), because it is not your activity, and even not the same task
You can't access any views of People app by the same reason
You cry a lot, because you don't know, what to do
But here I am with the solution. You need to use UiAutomation which can be obtained from instrumentation by calling final UiAutomation uiAutomation = getInstrumentation().getUiAutomation();.
Then you can't send any key events to another application, because it requires INJECT_EVENTS permission, which needs system signature, which your application apparently lacks :)
So, call this one:
uiAutomation.performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
It does not require any permissions and just work across application. Be sure you run your test above Android 4.3.
Additional link.

Prompt for default activity without actually opening activity

I need to set the default app for a specific mime type. I know how to clear the default but I need to then prompt the user without actually opening the app.
PackageManager p = mContext.getPackageManager();
ComponentName cN = new ComponentName(mContext, FakeDownloadActivity.class);
p.setComponentEnabledSetting(cN, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Intent selector = new Intent(Intent.ACTION_DEFAULT);
selector.addCategory(Intent.CATEGORY_DEFAULT);
selector.setType(mimeType);
mContext.startActivity(selector);
p.setComponentEnabledSetting(cN, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
The code above launches the activity rather than ONLY selecting the default activity. It works be enabling a fake activity then disabling it. This causes the Select Default App dialog to show the next time it is called. I simply want to ONLY select the default activity.
What you are looking for is an ACTION_PICK_ACTIVITY intent.
First, you create an intent that defines the apps that should be eligible to choose, for instance:
Intent mainIntent = new Intent(Intent.ACTION_DEFAULT, null);
mainIntent.addCategory(Intent.CATEGORY_DEFAULT);
Then, you create the ACTION_PICK_ACTIVITY intent, and as an Extra, you pass the main intent you created before
Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);
pickIntent.putExtra(Intent.EXTRA_INTENT, mainIntent);
Now, you just start an activity for result with this intent:
startActivityForResult(pickIntent, 0);
And a dialog will be created where the used can pick an application, but when clicked, the activity is not launched, instead, it will stay in your activity, and the function onActivityResult will be called with the results. So you need to create that function:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//In data, you have all the information about the selected application
if (data != null) {
//You can launch the application that we just picked with startActivity(data);
//or explore the variable to get all the information than you want
}
}
Take a look at the Intent class. There you have information about the package name, and the class that would be launched.
From now, what you need is to set that package and class as the default to the intent, or whatever else you need. The bad side, is that you only can save that information for your own internal purposes, for example to decide what app to launch next time that the users performs some action. What you cannot do is to modify the system settings to set a default activity for a given intent. Actually, the package manager has the addPreferredActivity method, that was supposed to do this, but it is deprecated since API level 8, giving this reasons:
This is a protected API that should not have been available to third
party applications. It is the platform's responsibility for assigning
preferred activities and this cannot be directly modified. Add a new
preferred activity mapping to the system. This will be used to
automatically select the given activity component when
Context.startActivity() finds multiple matching activities and also
matches the given filter.

Android - Open an external app and then call an intent URI

I have an app 'A'. I am opening another app 'B''s video player and playing a video using an intent URI call like so
String intentURI = "B://this/123";
try {
intent = Intent.parseUri(intentURI, Intent.URI_INTENT_SCHEME);
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
Logger.appendInfoLog("Something went wrong with B", TAG);
e.printStackTrace();
Logger.appendErrorLog(e.getMessage(), TAG);
finish();
}
startActivity(intent);
Now the necessary condition is for that app 'B' to be open in the background for this to work.If the app is closed(killed by Android or manually) or it has crashed,this throws an error.
Is there a way to open that app 'B' first or check its running status and then make the intent URI call. I will not get control back from that app and once I go to the other app I dont have any control on it until the user presses the back button to return to my app.
UPDATE:
I want to start app 'B' first and then call the intent programmatically. Is this possible
UPDATE
I Ran the Catlog app to check what message comes up in app B. It just shows file 123.file (The one i am trying to play in the app B's video player) not found, but when the app is running in the background it goes through fine. It also shows a warning
java.lang.NullPointerException: PrintLn needs a message
and then it says
Activity displayed, but mediaplayer.is not playingVideo
Also the other app is written in flash and packaged as a native app on adobe air
I have an app 'A'. I am opening another app 'B''s video player and playing a video using an intent URI call like so
No, you are not. You can tell that by reading the code -- there is no startActivity() call in that code block.
Now the necessary condition is for that app 'B' to be open in the background for this to work.If the app is closed(killed by Android or manually) or it has crashed,this throws an error.
Then apparently app B has a bug. Please contact the author of app B for assistance.
You can get a list of running apps easily.
ActivityManager manager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List<RunningAppProcessInfo> processes = manager.getRunningAppProcesses();
And you can launch apps just as easily.
Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage("com.package....");
startActivity(LaunchIntent);
You can't, however, launch an app into background, so this might not solve your issue.
You don't need to open that app 'B' first. Just check if that app is running with:
// Get running processes
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<RunningAppProcessInfo> runningProcesses = manager.getRunningAppProcesses();
So now you have all the running processes in runningProcesses. Just iterate over the values to find out if your app 'B' is running. An example of this iteration can be found here:
ActivityManager am = (ActivityManager)this.getSystemService(ACTIVITY_SERVICE);
List l = am.getRunningAppProcesses();
Iterator i = l.iterator();
PackageManager pm = this.getPackageManager();
while(i.hasNext()) {
ActivityManager.RunningAppProcessInfo info = (ActivityManager.RunningAppProcessInfo)(i.next());
try {
CharSequence c = pm.getApplicationLabel(pm.getApplicationInfo(info.processName, PackageManager.GET_META_DATA));
Log.w("LABEL", c.toString());
}catch(Exception e) {
//Name Not FOund Exception
}
}
Define the intent listener inside of your manifest file.
See the docs for details.
Basically, what you would do is in your AndroidManifest.xml of App B (the app you want to start with the Intent), add a section like:
<receiver android:name=".MyIntentReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Then inside of your MyIntentReceiver class, you would define the code to handle the intent.
public class MyIntentReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
// handle intent here
}
}
I think your problem is that Intent.parseUri() returns an Intent with the action ACTION_VIEW (see http://developer.android.com/reference/android/content/Intent.html#parseUri%28java.lang.String,%20int%29). And from your code, I gather that android does not recognize that it actually has to start activity B for this. ACTION_VIEW is generic, so id does what seems to be most appropriate. If activity B does not fall into that category (probably not the standard video viewing app), it' will not get launched. I would suggest the following:
Find out how to launch activity B (e.g. Intent i = new Intent.("com.packageB.ActivityB"); or similar. Developer should be able to tell you.
Use i.setData() to set the data of your intent to your file.
Use startActivity()
For step 2, there may be other ways Activity B needs the Uri passed. You can get this information from the developer as well.
Using startActivity rids you of having to check whether App B is running. Something that Android does anyway.
I think it is possible to start another apk from your own, just check this answer. The problem is that if you dont know their uri, it will be hard to do what you propose.
Now you can either ask the developers for the proper names or take a look at your own risk (i don't know about its legality).

Categories

Resources