Enable communication between two Android apps via custom permissions - android

One of my Android applications needs some features that are "dangerous" when it comes to permissions. They require some permissions such as "Internet access" which are critical in combination with private data.
This is why I want to create a separate "Add-on", i.e. a second app that provides these permission-critical features. So if users want them, they can install the add-on, but the main app will still work without those permissions.
Using a sharedUserId would obviously be the easiest solution, but adding this afterwards, when lots of users use the app already, could cause serious problems. Wouldn't this mean that the app can't access its own data any longer?
So I have to choose another approach. ContentProviders are something that I try to avoid, because they're too complex for this simple need in my opinion.
I thought custom permissions could solve the issue. Can they? I've added the following permission declaration to both the main app as well as the add-on as a child to the manifest tag in AndroidManifest.xml:
<permission
android:name="com.my.package.ADDON"
android:label="#string/permission_title"
android:description="#string/permission_description"
android:permissionGroup="android.permission-group.PERSONAL_INFO"
android:protectionLevel="signature" />
Furthermore, both manifest files have got this part now:
<uses-permission android:name="com.my.package.ADDON"></uses-permission>
The add-on app includes an IntentService that has the following attribute now:
android:permission="com.my.package.ADDON"
Shouldn't this do the job so that I can call the add-on's IntentService from my main app via this code?
Intent addonIntent = new Intent();
addonIntent.setClassName("com.my.package", "com.my.package.MyService");
startService(addonIntent);
Unfortunately, this call always fails with the following exception:
E/AndroidRuntime(16721): java.lang.SecurityException: Not allowed to start service Intent { cmp=com.mypackage.addon/.MyService } without permission com.mypackage.permission.ADDON
What did I do wrong? Thank you very much in advance!
Addition #1 - Add-on manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
package="com.mypackage.addon">
<uses-sdk android:minSdkVersion="8" />
<permission
android:name="com.mypackage.permission.ADDON"
android:label="#string/permission_title"
android:description="#string/permission_description"
android:permissionGroup="android.permission-group.PERSONAL_INFO"
android:protectionLevel="signature" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:permission="com.mypackage.permission.ADDON"
android:exported="true">
<service
android:enabled="true"
android:name=".MyService" />
</application>
</manifest>
Addition #2 - main app manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
package="com.mypackage.mainapp">
<uses-sdk android:minSdkVersion="8" />
<permission
android:name="com.mypackage.permission.ADDON"
android:label="#string/permission_title"
android:description="#string/permission_description"
android:permissionGroup="android.permission-group.PERSONAL_INFO"
android:protectionLevel="signature" />
<uses-permission android:name="com.mypackage.permission.ADDON"></uses-permission>
<application android:icon="#drawable/ic_launcher" android:label="#string/app_name" android:name="MyApp">
<activity android:name=".MainActivity" android:launchMode="singleTask" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

Wouldn't this mean that the app can't access its own data any longer?
Correct.
I've added the following permission
I would dump the permission-group, as that should not be necessary.
Furthermore, both manifest files have got this part now
Only the one calling your IntentService might need that.
Shouldn't this do the job so that I can call the add-on's IntentService from my main app via this code?
Not if that IntentService is not exported. Make sure that your IntentService either has an <intent-filter> or android:exported="true". I would recommend going the <intent-filter> route, so you can declare and use a custom action string, so you get away from hard-coding package and class names in the client app.
Here is a directory with two sample projects using this basic approach, though in my case the communications are based on a secured ContentProvider rather than a secured IntentService. The concept is the same, though, and so with these minor tweaks, I would expect what you are doing to work just fine.

Related

Android: get current device location without asking permission at run time

I've created a hospital related app where i want to know the whether patient has visited the doctor or not, getting the location is the requirement of my app.
I've used ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION permission in manifest. The problem is whenever application tries to get the location at run time the system prompts a security dialog which says "this app is trying to obtain your current location" and asks user to allow or deny it,, and if user clicks on the deny button the location is not fetched..
I don't want the user to click on the deny button is there any way i can skip this security dialog and set 'always allow' option in my app permission through code and get the location without ever prompting the user for access.
manifest file
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.kaizen"
android:versionCode="4"
android:versionName="1.1" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="22" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:name="com.kaizen.volley.VolleySingleton"
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.kaizen.SplashScreen"
android:configChanges="keyboardHidden"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.kaizen.Login"
android:windowSoftInputMode="stateHidden|adjustResize" />
<activity
android:name="com.kaizen.AppMenu"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateHidden|adjustResize" />
<activity
android:name="com.kaizen.SignUp"
android:windowSoftInputMode="stateHidden|adjustResize" />
</application>
The dialog you're seeing surely is a vendor specific feature. E.g. there is some function called KNOX for Samsung business devices, that seems to behave like what you're seeing. Once you found out where it comes from exactly, I wouldn't care about it any further. This is not widely spread and in those cases where the message pops up it will do for a reason: the user wants (or is forced by his administrator) to be informed about certain actions, such as apps wanting to get the current location.
You may check the normal behavior of your app in an emulator, if you do not have another device.

Defining your own permissions in android

I am trying make my own permission for android application.
For this my android manifest file looks like this.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.hp.happybirthday" >
<permission
android:name="com.example.hp.happybirthday.PERM"
android:description="#string/pdesc"
android:label="#string/CAREFUL"
/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:permission="com.example.hp.happybirthday.PERM">
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
The problem that I am facing is that I want to have my own permission associated with this application and hence i have added the following line as shown above under the application tag, so that only those activities have access to this app which possess my defined permission.
android:permission="com.example.hp.happybirthday.PERM"
But the problem is that when I try to run my app, the app whose manifest file I have declared, it shows the error app is not installed.
But when I remove the above mentioned line, it works, but then any activity will have access to this app which I do not want.
when I try to run my app, the app whose manifest file I have declared, it shows the error app is not installed
That is because the home screen is an app, and the home screen does not hold your custom permission. Hence, the home screen cannot start your launcher activity.
then any activity will have access to this app which I do not want
First, custom permissions do not work all that well.
Second, permissions are usually applied at a finer granularity than "this app". You only secure those components that need the security, and you leave public other components, like the launcher activity.
It looks like you've defined the permission, and set it to be required... but you haven't actually granted it to your own app. Add a uses-permission tag

Why does the Android app Keyguard not contain any components?

Below is the shortened content of AndroidManifest.xml of the app Keyguard of Lollipop located at: $(AOSP_Root_Dir)/frameworks/base/packages/Keyguard/
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.keyguard"
android:sharedUserId="android.uid.systemui"
coreApp="true">
<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17"/>
<application android:label="#string/app_name"
android:process="com.android.systemui"
android:persistent="true"
android:supportsRtl="true">
</application>
</manifest>
What's weird is: There is NO any components such activity, service, etc. in AndroidManifest.xml!
How does it get started?
I'm not sure what you intended to take out when you edited this to a shortened form, but looking at the version you link to it certainly does include a service thus:
<service android:name=".KeyguardService"
android:exported="true" />
EDIT: In the version you now link to, that service was removed by the checkin:
https://github.com/android/platform_frameworks_base/commit/380ecb81db52a9d0197ca969951d07b91c20d2b9
which did the following:
Let Keyguard be a library, so we can use it in SystemUI.
Implement a new KeyguardService in SystemUI, and bind that service
from PhoneWindowManager.

make android application performance better

my android application performance is low, it takes a long startup time. i have 5 buttons, one imageview, 3 textView, 2 editText and one listView initialized in onCreate() method. Is large number of ui object the reason for slow startup?? Is there any fault in manifest.xml??
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ars.application"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="#drawable/lightvasicon" android:label="#string/app_name" android:debuggable="true">
<activity android:name=".LightVas"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:configChanges="keyboardHidden|orientation" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<uses-permission
android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"></uses-permission>
<uses-permission
android:name="android.permission.ACCESS_MOCK_LOCATION"></uses-permission>
<uses-permission
android:name="android.permission.CONTROL_LOCATION_UPDATES"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-sdk android:minSdkVersion="7" />
</manifest>
Generic performance advice:
In most cases you shouldn't try to guess what is causing performance problems as intuition is often wrong. If you knew the cause of slow code, you wouldn't have written it slow in the first place!
Use the profiler to work out where your performance problems are.
Optimize just the slow parts. Keep a copy of your traces and compare them after making a change, so you know whether you're heading in the right direction or not.
Make your own simple timing method to verify your results, this will make sure that trace recording itself is not causing performance issues in a different place.

How to keep an Android app running indefinitely?

I am writing an Android app which must always be running in the background until the user exits it from the app's menu. But now I notice that in Android after some time my app is stopped by itself without user intervention.
Any idea how to make sure my app will always be running in the background?
You need to run a Service of your own.
http://developer.android.com/reference/android/app/Service.html
If you need to run at all times, look into a Service and startForeground. If you can let your Service die but get restarted, look into onStartCommand and START_STICKY.
AndroidMainfest.xml looks like this with presistent=true:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="7" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" android:persistent="true">
<activity
android:name="com.example.test.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
“While the app development documentation does explain the role of
android:persistent, the use of that attribute is reserved for apps that
are built within the AOSP.”
– Embedded Android
For your application, in the manifest xml, put:
android:persistent="true"

Categories

Resources