I have seen some of example where other application can start my application by package name. Due to security reason I want to prevent this kind of access for other application.
I want to prevent this (Open another application from your own (intent)) kind of acess
Edit
For Example, If thirdparty application knows my application's package name they can launch my app from their application like this way,
Intent i;
PackageManager manager = getPackageManager();
try {
i = manager.getLaunchIntentForPackage("app package name");
if (i == null)
throw new PackageManager.NameNotFoundException();
i.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(i);
} catch (PackageManager.NameNotFoundException e) {
}
Now to prevent this, i have added export = "false" in my launching activity as well as added permission to lauching activity. Now due to this, it is preventing thirdparty app to launch my application but android OS launcher is also not able to launch application.
I imagine if you don't provide the launch intent in your Android manifest, other apps (including your homescreen) won't be able to launch your app.
You can try these attributes in manifest:
http://developer.android.com/guide/topics/manifest/activity-element.html#exported
http://developer.android.com/guide/topics/manifest/service-element.html#exported
http://developer.android.com/guide/topics/manifest/receiver-element.html#exported
http://developer.android.com/guide/topics/manifest/provider-element.html#exported
As also mentioned in those links, you can try another approach by using permission with the protectionLevel = signature
http://developer.android.com/guide/topics/manifest/permission-element.html#plevel
I hope below solution by comparing package name will help you protecting your activity to be launched by other app.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ComponentName componentName = this.getCallingActivity();
if(componentName == null) {
finish();
} else if("<intended package name>".equals(componentName.getPackageName())) {
finish();
} else {
String data = getIntent().getDataString();
...
}
}
}
Above solution is base on below assumption:
Only one app with a particular package name can exist on Google Play.
If a user tries to install an app whose package name already exists on the device, the installation either will fail or will overwrite the previously installed app.
Related
I have two very similar news apps on the Play Store, let's call them app A and app B (B is similar to A, but has advanced features). Now I want all my users of app A to seamlessly migrate to app B. For that, I wish to push an app update to A, with a button titled "Upgrade to B now". When the button is tapped, I want to do two things. One is to check if B is not installed, and if it isn't I want to start downloading the app B, then proceeding to install it. Once the app is installed or if it were already installed, I wish to pass on login information to the app B and open its home page(probably using intents). The second is to delete app A once migrated to B. How can this be accomplished as seamlessly as possible so as to give the users of app A, an opportunity to start using the much better app B, with the transition happening automagically behind the scenes?
I went through a few posts with people downloading custom apks, and then installing it programmatically. So probably what I could do is download the apk of B from my server, and then install it after INSTALL_PACKAGES permission is granted by the user. Is this the right way to go about this?
once the user clicks the install button. check whether the app B installed otherwise you can direct him to the playstore of app B, use the below code to achieve this.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add respective layout
setContentView(R.layout.main_activity);
// Use package name which we want to check
boolean isAppInstalled = appInstalledOrNot("Package name of your App B");
if(isAppInstalled) {
//This intent will help you to launch if the package is already installed
Intent LaunchIntent = getPackageManager()
.getLaunchIntentForPackage("Package name of your App B");
startActivity(LaunchIntent);
Log.i("Application is already installed.");
} else {
// Redirect to play store
Intent i = new Intent(android.content.Intent.ACTION_VIEW);
i.setData(Uri.parse("https://play.google.com/store/apps/details?id=Package name of your App B"));
startActivity(i);.
Log.i("Application is not currently installed.");
}
}
private boolean appInstalledOrNot(String uri) {
PackageManager pm = getPackageManager();
try {
pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
return true;
} catch (PackageManager.NameNotFoundException e) {
}
return false;
}}
Hope i gave you an solution :)
I have a simple Android app that needs to launch another app under certain condition, and I will need to check the condition upon the app launch. That is, either continue to launch my app or just launch another app:
if (A == true) {
launch another activity of another app
leave the current app without creating the main activity
} else {
launch the main activity of the current app
}
Could anyone please let me know how to deal with A == true case? I am able to launch another app's activity but I have trouble leaving the current app without even opening the main activity.
Any help will be greatly appreciated!
You can launch other application using following intent
Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage("com.example.abc");//pass the packagename of app you want to open
startActivity( LaunchIntent );
If you don't know the package name of application that you wanted to launch then try your hand on
PackageManager pm;
pm = getPackageManager();
// get a list of installed apps.
packages = pm.getInstalledApplications(0);
Pass the packagename of app you want to open
You can use this if A == true
else You can launch the MainActivity as
startActivity(new Intent(CurrentActivity.this,MainActivity.class));
If you want to start another activity of another app without the normal IntentFilter then the easiest solutions is:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName("com.anotherapp.package","com.anotherapp.package.MainActivity"));
startActivity(intent);
Of course, you would need to know the package name and the Activity name you want to start
As for finishing your application call
finishAndRemoveTask();
I have two apps and I want to switch between the apps after clicking on a button.
I use this code:
PackageManager manager = getPackageManager();
Intent i = manager.getLaunchIntentForPackage("at.mycompapp");
if (i == null) {
return;
}
i.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(i);
My problem is that the app is started new, but when the app is already running, it should just switch to this app without restarting it.
I am now using custom scheme to get to the right point in my apps.
I am trying to open the Google Voice Search Application
Intent i;
PackageManager manager = getPackageManager();
try {
i = manager.getLaunchIntentForPackage("com.google.android.voicesearch");
if (i == null)
throw new PackageManager.NameNotFoundException();
i.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(i);
} catch (PackageManager.NameNotFoundException e) {
}
This does not launch the voice search application,
however if I use com.google.android.apps.maps as the package name then the Google Maps app is opened.
I don't understand why Voice Search is not opening, even though the package name is correct.
Solution
Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
startActivity(intent);
Please see
Launch Preinstalled App from activity (Google Voice Search) Android for more information on the solution.
Thank you.
As you can read here, getLaunchIntentForPackage (String packageName)
Return a "good" intent to launch a front-door activity in a package [...]
The current implementation will look first
for a main activity in the category CATEGORY_INFO, next for a main
activity in the category CATEGORY_LAUNCHER, or return null if neither
are found.
so, in the intent, the category will already be set. If you manually change it, probably you are breaking the intent, since the category could not be the correct one that the manager found.
so, just remove the line
i.addCategory(Intent.CATEGORY_LAUNCHER);
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).