How to stop an activity to be accessed from another app? - android

In my app I have two activities:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SecondActivity"/>
So my SecondActivity can be accessed from another app. I think it's a security issue, so how can I stop this? Is this somehow related with exported setup?

Within three steps you can do it.
define a permission (which is only available to applications having your signature)
define that your application uses your defined permission
require that permission for the activities you want protected. (Be careful to not require it for your main launch activity).
<!-- to define a permission -->
<permission
android:protectionLevel="signature"
android:name="com.example.MYPERMISSION"/>
<uses-permission android:name="com.example.MYPERMISSION" />
<!-- to define an activity which can only be started through internal code -->
<activity android:name="..."
android:permission="com.example.MYPERMISSION" >
...
</activity>

android:exported = false in AndroidManifest inside activity tag should do the work

Related

How to work with permissions in single activity design using navigation component?

My previous app has many activities and some of them are declared as exported true, so that other apps can call them through intent filter.
Some of them also has specific permission which also sets in my activities.
Now, i am developing a app using single activity.
So, i am curious to know how can i handle this permission issue in single activity design, as i have only one activity.
Previously, in multiple activities i can easily set permission in specific activity. How can i handle this here?
I am a newbie. I searched a lot but did not find any clue.
Edit:
Multiple activities declaration:
<permission
android:name="com.example.permission"
android:protectionLevel="signatureOrSystem"
tools:ignore="SignatureOrSystemPermissions"
/>
// Activity 1: With permission, exported = true
<activity
android:name=".place"
android:configChanges="keyboardHidden|orientation|screenSize|screenLayout"
android:exported="true"
android:label="place"
android:permission="com.example.permission" // Sets a permission
android:theme="#style/Theme.AppCompat.DayNight.NoActionBar">
<intent-filter>
<action android:name="com.action.places" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
// Activity 2: With no permission, exported = true
<activity
android:name="userCheck"
android:configChanges="mcc|mnc|keyboard|keyboardHidden|orientation"
android:exported="true"
android:theme="#style/Theme.AppCompat.DayNight.NoActionBar">
<intent-filter>
<action android:name="com.confirm.passowrd" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Now, i want to move to single activity.
// Single activity: exported = true. How can i handle permission for place action?
<activity
android:name="com.example.singleActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<!-- Place -->
<action android:name="com.action.places"/> // How can i handle permission for this action?
<!-- UserCheck -->
<action android:name="com.confirm.passowrd" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
You can't use manifest-based permissions if you want to restrict a single Activity from being launched in some cases but not others. The manifest-based permission controls access to the specific Activity, no matter how it is being launched.
What you could do is create an <activity-alias> for your single Activity. An <activity-alias> is a manifest entry that references an actual Activity, but provides alternate launch options. You can specify a different set of permissions on the <activity-alias> than the ones you have on the actual Activity. You can also specify different launchMode, different <intent-filter>, etc.

Android manifest for USBAccesory

I am making an app that communicates with a piece of usb hardware made by my company (this is the only app allowed to talk to the usb accessory, it's not a public api). I am having difficulties setting up the proper launch modes in the manifest.
There are three components to the app: the main activity, a login activity, and the USBService.
I'm assuming the intent for the main goes to the login activity, and the intent for the usb goes to the USBService, but I am not sure if I do this, will this start the service if the app is not running? More over, if it does, how do I fetch an already existing service?
What type of structure should I be looking at for the manifest file? (specifically, intent-filters, and appropriate launch modes... I've read a few documents about the launch modes but I am still not sure I quite understand... There should only ever be at most one instance of each activity/service, and they need to communicate together.
edit: it is not necessary for communications to start before the app is open, nor is it necessary to launch the app automatically when the usb is connected.
edit: my manifest as it stands, looks like:
<uses-feature android:name="android.hardware.usb.accessory" />
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name="mainpackage.MainActivity"
android:label="#string/app_name"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="#xml/accessory_filter" />
</activity>
<activity
android:name="mainpackage.LoginActivity"
android:label="#string/title_activity_login"
android:windowSoftInputMode="adjustResize|stateVisible" >
</activity>
<service android:name="updater.USBService"
android:exported="false" >
<!--
-->
</service>
</application>
in your manifest add
<manifest ...>
<uses-feature android:name="android.hardware.usb.host" />
<uses-sdk android:minSdkVersion="12" />
In this case, the following resource file should be saved in res/xml/device_filter.xml and specifies that any USB device with the specified attributes should be filtered:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device vendor-id="1234" product-id="5678" class="255" subclass="66" protocol="1" />
</resources>
Hope this help.
Your manifest looks good,
I think you make a good choice for putting the intent-filter "android.hardware.usb.action.USB_ACCESSORY_ATTACHED" in the mainActivity and start the application in this activity,
and again I think it's a good choice to start your mainActivity in SingleTop launch mode,
because if an instance of the mainActivity already exists at the top of the current task, the system going to launch this activity, no new instance of this activity will be created.
For a best understanding of the different launch mode available in android,
I think this link may help you :
http://www.intridea.com/blog/2011/6/16/android-understanding-activity-launchmode
To make a long story short I think you'll be all set with this manifest as is.
To Use Android Devices min SDK version should be set to 12 and need to declare following line in AndroidManifest.xml file
<>
<uses-sdk android:minSdkVersion="<version>" />
...
<application>
<uses-library android:name="com.android.future.usb.accessory" />
<activity ...>
...
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="#xml/accessory_filter" />
</activity>
</application>

Android first app, all activities visible in menu

I just created my first Android app, all works fine, but all of the activities are shown on my Android menu. What did I do wrong?
Screenshot: imgur.com/9CmXU
I want to have one icon, directing to MainActivity, not all activities
<!-- language-all: lang-html -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myApps.birthdaymeter"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<application
android:icon="#drawable/my_logo"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".BirthdayMeter"
android:label="#string/title_activity_birthday_meter" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".AboutWindow"
android:label="#string/title_activity_about_window" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ShowResult"
android:label="#string/title_activity_show_result" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
This is my manifest, changing logo didn't help
The <intent-filter> tag is used to describe the type of Intents that each Activity will respond to. The "android.intent.action.MAIN" action says that this Activity is an entrance point for your Application (think the main method that a java program requires). The "android.intent.category.LAUNCHER" category tells the OS to display the Activity in your list of Applications. Adding the DEFAULT category is ok, but effectively the same as omitting the <intent-filter> tag completely (which I find to make for much cleaner and easier to read code). You should only be using the <intent-filter> tag with these two actions and categories on the Activity that starts when a user opens your app. If wanted an Activity within your application to be able to respond to some special intents, you would use the tag to define which it responds to.
Here's a link to the google dev pages to help you learn more about Intent Filters.
http://developer.android.com/guide/components/intents-filters.html
Here's the documentation for the <intent-filter> tag. It's not the easiest to understand though.
http://developer.android.com/guide/topics/manifest/intent-filter-element.html
And here's the docs for the Manifest file and the Intent class. Both of these are good for reference if you're not sure about which tags to use in your Manifest. Good luck!
http://developer.android.com/guide/topics/manifest/manifest-intro.html
http://developer.android.com/reference/android/content/Intent.html
You phrased your question extremely generally, so I am not sure what to answer. It seems like you haven't called nameOfActivity.this.finish() when you launched another activity
If you post your manifest file I can help a little more, but it looks to me like you have not declared your activities correctly.
It should be setup somewhat like this:
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name="Activity1"></activity>
<activity android:name="Activity2"></activity>
<activity android:name="Activity3"></activity>
</application>
Essentially, create an application declaration, and then include each activity within it.

How can I access to my application which is already running?

I run my application "A" normally with the launch icon in the "Applications" menu.
I press the home button, so my application "A" is still running on my phone.
Now I browse my files presents in my phone, and I use the share action to share this file with my application "A".
The file is sharing perfectly, but instead of using the instance of my application already opened, it opens a new instance of my application "A".
If I quit this new instance, the first instance is still running and it's a problem concerning the security goal of my application.
I try to use the FLAG_ACTIVITY_CLEAR_TOP to use the activity in the first instance, but it doesn't work because it isn't the same application which is launched by the OS.
Is there a way to do this ? And if yes can you give me some hints or some leads to follow ?
My manifest :
<?xml version="1.0" encoding="utf-8"?>
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="8" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar" >
<activity android:name=".SplashScreenActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ExplorerActivity"
android:configChanges="orientation|keyboardHidden"
android:theme="#android:style/Theme.Light.NoTitleBar" >
</activity>
<activity
android:name=".ChooseDialogActivity"
android:theme="#android:style/Theme.Translucent.NoTitleBar" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
</application>
Here is my manifest. Usual process : SplashScreenActivity -> ExplorerActivity
Share process : ChooseDialogActivity -> ExplorerActivity
What I want, it's that the second ExplorerActivity has to be the same that the first ExplorerActivity if this activity already exists.
Please don't use launchMode="singleInstance". This is not what you want. singleInstance is only for HOME-screens and similar apps.
Try instead to use Intent.FLAG_ACTIVITY_NEW_TASK when sharing. This will separate your application from the files-browsing application and may get the behaviour you want. You may also need to add FLAG_ACTIVIY_CLEAR_TOP as well, depending on how you've programmed your app.
EDIT
When you launch ExplorerActivity from ChooserActivity, do this (or something similar):
Intent intent = new Intent(this, ChooserActivity.class);
intent.addFlags(Intent.ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
If there is already a task running that contains the ChooserActivity, this should bring that task to the foreground instead of creating a new instace of ChooserActivity.
use the launchmode this will keep one instance from your main activity so make this change for the home activity .
<activity ..
...
..
android:launchMode="singleInstance" />
try android:launchMode="singleInstance"

Problem calling activity from another package in Android

Situation:
I need to combine several apps into one .apk app. Lets say implement app2 into app1
What i have done:
Copied app2 package into main app1 project which i am working, so my app1 has two packages.
app2 had this manifest file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.package.app2" android:versionCode="3" android:versionName="1.2">
<application android:label="App2" android:icon="#drawable/icon">
<activity android:name="Activity1" android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="Activity2" android:excludeFromRecents="true"></activity>
</application>
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
<uses-permission android:name="android.permission.VIBRATE"></uses-permission>
</manifest>
My original App1 manifest file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.package.app1">
<application android:icon="#drawable/icon" android:debuggable="true">
<activity android:name=".Start" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.package.app1.PlayerList" />
<activity android:name="com.package.app1.CreateNewPlayer" />
<activity android:name="com.package.app1.Profile" />
<activity android:name="com.package.app1.Braintrainer" />
</application>
</manifest>
The code in app1 i am using to call activity in app2 package:
Intent i = new Intent();
i.setClassName("com.package.app1", "com.package.app2.Activity1");
startActivity(i);
The question:
How do i modify my app1 manifest file to have activities of app2.
Things i`ve tried:
It works if i create simple HelloWorld test class in app2, call using the same code and just include this in the app1 manifest:
<activity android:name="com.package.app2.Test" />
But i can not figure out how to implement the app2 manifest file into the first one. Every way i try give no errors but crashes when calling that activity. App2 alone works fine, so problem not in the activity file.
Appreciate any thoughts on this.
Intent i = new Intent();
i.setClassName("com.package.app1", "com.package.app2.Activity1");
startActivity(i);
Shot in the dark:
change com.package.app1 to com.package.app2. I've called done what you're attempting right now, and I've always had to specify the package of the class I wanted to call.
Ok, PackageManager is not your solution, I misread and thought you had two apps and wanted one app to call the other. It looks like you just want one app.
Modify your app1's manifest like this:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.package.app1">
<application android:icon="#drawable/icon" android:debuggable="true">
<activity android:name=".Start" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.package.app2.Activity1" />
<activity android:name="com.package.app2.Activity2" android:excludeFromRecents="true"></activity>
<activity android:name="com.package.app1.PlayerList" />
<activity android:name="com.package.app1.CreateNewPlayer" />
<activity android:name="com.package.app1.Profile" />
<activity android:name="com.package.app1.Braintrainer" />
</application>
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
<uses-permission android:name="android.permission.VIBRATE"></uses-permission>
</manifest>
And try the first way again.
I have several packages and need to do something similar in my app.
You need to be careful with this technique, otherwise you'll experience nasty memory leaks.
I declared my activity in my base controller (activity) class as a static variable. All controller classes inherit from this class, so all controller classes are able to access it. Pass in the activity as an argument for anything outside of the controller classes that need to access the activity.

Categories

Resources