RestrictionManager getRestrictions() is always empty - android

I'm trying to set-up the remote configuration for my app with MobileIron EMM. I've done everything as described in developer guide:
1. I've set-up the manifest:
...
<meta-data
android:name="android.content.APP_RESTRICTIONS"
android:resource="#xml/app_restrictions"/>
</application>
2. I've described the restriction:
<?xml version="1.0" encoding="utf-8"?>
<restrictions xmlns:android="http://schemas.android.com/apk/res/android">
<restriction
android:title="#string/some_title"
android:key="SOME_KEY"
android:restrictionType="string"
android:defaultValue="123"/>
</restrictions>
3. I'm trying to receive it as following:
RestrictionsManager manager = (RestrictionsManager) context.getSystemService(Context.RESTRICTIONS_SERVICE);
Bundle b = manager.getApplicationRestrictions();
if(b!=null){
if(b.containsKey("SOME_KEY")) {
return b.getString("SOME_KEY");
}else{
System.out.println("bundle is not null");
for (String s: b.keySet()){
System.out.println("key in b is : " + s);
}
System.out.println(b.isEmpty() + " bundle is empty");
}
}else{
System.out.println("Bundle is null");
}
return "";
}
I've always got the output:
bundle is not null
true bundle is empty
although I've set the default value for the restriction. Why am I not getting at least default value for the restriction? Why am I never get an actual values (at the server side I've set the values with MobileIron Cloud and its AppConnect configuration)? Tried with several devices. What am I missing? Please help. My goal is to remotely set-up some key-value to the app.

If you're not receiving any restrictions at all then it's probably because your app isn't part of a managed profile. App restrictions only work in two scenarios... your device has been provisioned using your EMM console (can only be done after a factory reset) or your device has an Android for Work profile that is managed by your EMM console. You don't actually need to declare each restriction in the manifest, that only allows the EMM to provide that information in their console.
The easiest way to test your app restrictions on an unprovisioned device is to download the Test DPC app from the google play store. Setting it up will encrypt your device and install a work profile you can use for testing. You can use the DPC app to simulate applying app restrictions, reading the restrictions from manifest, and a number of other things EMMs do. You can install your app on the work profile using adb or by following the developer's guide to tell Android Studio how run the app in your work profile.
https://developer.android.com/work/guide.html#testing

These two posts should help post1 and post2.
Fred helped me understand from those posts, but to summarize:
If an item has not been explicitly set by a managed configurations provider, then that item will not be in the Bundle. An empty, but "not null" bundle just means nothing has been set by a managed configurations provider. The defaultValue in the managed configurations XML file is not used here. And the app is not being actively managed.
To get the defaultValue, query the configuration item's value using this RestrictionsManager.getManifestRestrictions(). It returns a list of all the RestrictionEntry objects as they are set in the managed configuration XML file. This means the value of the item is the defaultValue as defined in the XML file.

I had the same problem. We have tested with an Xamarin csharp app, used the public google test app "Test DPC" available via Play Store. It has a button "Load manifest restrictions" that should be able to load the app restrictions defined (it did not, in my case anyway).
It worked only, if:
I did NOT debugged the application (there the values applied with DPC always not defined/empty) but started at the device directly, and
add/set the key/value pairs manually within the Test DPC app.
Then I got my boolean values switched from within DPC... (ensure you pressed "Save" within "Manage applications" screen)

Related

Amazon IAP Android onProductDataResponse always fails

I am trying to implement a simple subscription IAP on Android using the Amazon SDK. I adjusted their subscription sample app. The code is really simple.
Set <String>productSkus = new HashSet<String>();
productSkus.add("TLS_SKU_MONTHLY" );
productSkus.add( "TLS_SKU" );
PurchasingService.getProductData(productSkus);
But the response from onProductDataResponse() is always fail. I'm not sure why, I cannot find any examples etc to even know if my SKUs are right, in the sample app they looked more like package names than this, but these strings are what I entered on the 'in-app items' on the apps page on Amazon. The app has not been submitted yet, but I need to test and implement IAP before that. Any ideas? I cannot even find a simple tutorial walking through this, and as usual their docs are poor.
edit, noticed im getting these errors that dont even come up on google
Kiwi: DataAuthenticationKeyLoaderV3: Unable to load authentication Key
java.io.FileNotFoundException: AppstoreAuthenticationKey.pem
DATA_AUTH_KEY_LOAD_FAILURE: CERT_NOT_FOUND: null
com.amazon.a.a.o.b.a.a: DATA_AUTH_KEY_LOAD_FAILURE: CERT_NOT_FOUND: null
I'm wondering, is this because I am running on real Android and not an Amazon device like a fire tablet or tv stick?
You should add your own AppstoreAuthenticationKey.pem to the project assets folder. It is not (and should not be) delivered together with the sample.
Basically, you must do a few things:
Login to the Amazon developer console and create your application.
Go to the “Apk Files" tab to download AppstoreAuthenticationKey.pem.
Add this file to the project’s assets folder.
You can get the full instructions from Amazon.
As for devices, yes, you must use an Amazon device. But this should not be the reason why you are getting this exception.

Integrating Air Watch Android Studio

I am very much new to AirWatch Concept but had gone thoroughly about AirWatch. I have gone through the following links,
http://developer.air-watch.com/android/application-configuration-with-the-android-sdk/
http://developer.air-watch.com/android/android-sdk-setup/
but in vain.
Could anyone please help me regarding the integration of Air Watch in Android ?
Things i have done so far,
I have created app in the https://apidev.awmdm.com, and i have added assignemnts. The question here is, How can i get the assignment details in my android application that were added in the Air Watch Console.
Help is really appreciated.
Update:
I am able to create and push the application from AIR WATCH CONSOLE to my Device. Now, the issue i am facing is, If i am adding some application configuration in the AIR WATCH CONSOLE, i am not able to get those details in my application.
I have gone through the below Url for the above scenario,
https://appconfig.org/android/ which is very much similar to https://appconfig.org/ios/
I have implemented those things that were mentioned in the above url but still then i am not able to get those details.Please let me know if i am wrong anywhere.
I got to know that the key value pairs that were being passed in Air watch console will be coming into com.apple.configuration.managed key in iOS. Does any one have an idea that how these key value pairs will come. As far as i know, they will be handled via Restriction Manager. But no idea/clue how to handle in Android.
Updated:
xml/app_restrictions.xml:
<?xml version="1.0" encoding="utf-8"?>
<restrictions xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<restriction
android:key="ManagedServer"
android:restrictionType="string"
android:title="Managed Server"
tools:ignore="ValidRestrictions" />
<restriction
android:key="#string/mdm_key_managed_server_name"
android:restrictionType="string"
android:title="#string/mdm_key_managed_server_url"
tools:ignore="ValidRestrictions" />
<restriction
android:key="#string/mdm_key_managed_server_url"
android:restrictionType="string"
android:title="#string/mdm_key_managed_server_url"
tools:ignore="ValidRestrictions" />
</restrictions>
oncreate Method :
IntentFilter restrictionsFilter =
new IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);
BroadcastReceiver restrictionsReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Get the current configuration bundle
Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();
// Check current configuration settings, change your app's UI and
// functionality as necessary.
Toast.makeText(LoginActivity.this, "Reciever Called", Toast.LENGTH_LONG).show();
RestrictionsManager myRestrictionsMgr =
(RestrictionsManager)
getSystemService(Context.RESTRICTIONS_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
if (myRestrictionsMgr != null) {
Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();
if (appRestrictions != null) {
if (appRestrictions.containsKey("ManagedServer")) {
String mConfigDetails = appRestrictions.getString("Managed Server");
Toast.makeText(LoginActivity.this, "" + mConfigDetails, Toast.LENGTH_LONG).show();
}
}
}
}
}
};
registerReceiver(restrictionsReceiver, restrictionsFilter);
List of Users:
When i am actually trying the other command:
Update:
Created a sample app and published to Play Store. App link as follows,
https://play.google.com/store/apps/details?id=com.manu.samplemdm
Now, its a play store app. When I am sending Application Configuration but unable to receive it in the Application. Its giving me still empty bundle from the application.
Help would be really appreciated.
Help is really appreciated
Beside AirWatch Resources, which tells you how you can create an app and set the app configurations,key-value pairs, to push to your devices, You need to check out Android Restriction Manager API. Follow the steps described in the link.
How the whole process works is, AirWatch controls AndroidForWork environment after you set your MDM as AirWatch. And then, AirWatch manages the device from AirWatch console and it pushes the App Configuration to AndroidForWork in your device. You need to implement Android Restriction Manager to access to these data passed you by your MDM. It goes same for all of the MDMs in the Market.
Update:
In order to install your app into Work Container in the development phase, you can use adb to copy it from Personal Container to Work Container.
First, list all of the active users in the device:
./adb shell pm list users
And later, find the Work User's ID from the List of Users and set it in the command below along with your app's package name and App's Main Activity.
./adb shell am start —user 13 -n “your.apps.package.name/your.main.activity.package.name”
13 up there in the command is the Work User's ID. In my case, it's 13.
For more information about ./adb commands in Managed Profiles, see this link and check the most bottom of the page.
There are a couple of different approaches to integrating with AirWatch. It depends on the technology set you're trying to use. I think these are the 2 that are most relevant to you based on what I see in your post:
AirWatch SDK
AppConfig Standard
Both these approaches can accomplish similar functionality but each have different deployment requirements. It sounds like you have gone with the second approach which is using the AppConfig standard and the native APIs provided by Google to have an app read configuration values delivered through AirWatch.
One important thing to note is the AppConfig standard approach on Android requires the device to support "Android for Work" enrollment which is a relatively newer management protocol released by Google. It's worth noting that AirWatch does support Android for Work enrollment so it may just be a matter of getting your AirWatch test instance configured for "Android for Work enrollment" instead of the traditional older Android enrollment protocol. More information about Android for Work can be found here:
https://enterprise.google.com/android/solutions/personal/
If you're already a customer of AirWatch, it may be helpful to create an account here on their resource portal if you haven't done so already to get access to documentation about how you can setup Android for Work within AirWatch. https://resources.air-watch.com
I hope this helps.

Registering a Google account to Android device programmatically

I've been looking for a solution to this problem for a while (days, not minutes), but it eludes me quite effectively.
Please note that this is NOT a question about starting up the registration procedure. This must happen automatically without any user interaction.
I would like to add a Google account to my custom device (1000's of them). The account will mostly be used to activate Google Play store on the device so that the app can update when newer versions are available.
My existing code (the shortest snippet of those I tried):
AccountManager mgr = AccountManager.get(this);
Account acc = new Account("email#gmail.com", "com.google");
mgr.addAccountExplicitly(acc, "password", new Bundle()));
naturally yields a
java.lang.SecurityException: caller uid 10047 is different than the authenticator's uid
So how would I go about actually achieving this? My device is rooted so that's not an obstacle if it's the only way.
It is not possible to add/create a Google account using addAccountExplicitly(). You can only add accounts for your own services. even your device is rooted because it will rejected by Google web server. For more detail check this link
Warning: this solution doesn't work well. See comments for explanation.
Well, as it turns out, this is not something easily solved. I ended up registering one device, then pulled the users file from it. Location of users file : /data/system/users/0/accounts.db (if there are multiple user profiles on the device, the last directory may differ according to profile in question).
I stored this file into my app's assets (gzipped, make sure the extension is not something.gz because that gets lost during packaging - didn't bother checking out why).
First I check if my user already exists:
AccountManager mgr = AccountManager.get(this);
for (Account acc: mgr.getAccountsByType("com.google")) {
if (acc.name.equalsIgnoreCase("email#gmail.com"))
return;
}
If it does, I just skip the step. Otherwise I unpack the users file and overwrite existing one (using su). I then also do a reboot to make sure changes are registered.

Cannot add new custom account from different app with same authenticator

I have two apps that both use a same custom account type. Those two apps are completely independent and just share the account. When one of them starts, it checks for existing custom accounts and if no account was found, shows the sign-in page.
So I have created my AccountAuthenticator as a library project and reference it in both apps. According to this tutorial:
Let’s say you copied your authenticator’s code to 2 of your apps, thus
sharing its logic, and altering the sign-in pages design on each app
to fit the app it belongs to. In that case, the first installed app’s
authenticator will be called for both apps when an auth-token will be
requested. If you uninstall the first app, the second app’s
authenticator will be called from now on (since it’s the only one
now).
When I run one of the apps (no matter which app) and call addAccount it shows the sign-in page well. Then, when I run the second app and call addAccount nothing happens and sign-in page is not shown. After uninstalling the first app, the second app works correctly and shows sign-in page. So what is the problem and how can I fix that?
The implementation of addAccount:
mAccountManager.addAccount(accountType, authTokenType, null, null, this, new AccountManagerCallback<Bundle>() {
#Override
public void run(AccountManagerFuture<Bundle> future) {
try {
Bundle bnd = future.getResult();
showMessage("Account was created");
} catch (Exception e) {
e.printStackTrace();
showMessage(e.getMessage());
}
}
}, null);
Thanks in advance
#Misagh Emamverdi Yeah .You missing that permission in your manifest .
android:sharedUserId
The name of a Linux user ID that will be shared with other applications. By default, Android assigns each application its own unique user ID. However, if this attribute is set to the same value for two or more applications, they will all share the same ID — provided that they are also signed by the same certificate.
Application with the same user ID can access each other's data and, if desired, run in the same process.
So android:sharedUserId is used to share the processes between two or more applications (Like Udinic Authenticator).
SYNTAX
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="string"
android:sharedUserId="string"
android:sharedUserLabel="string resource"
android:versionCode="integer"
android:versionName="string"
android:installLocation=["auto" | "internalOnly" | "preferExternal"] >
. . .
I'm not sure this the correct answer, but I found that the problem is that the apps have different UIDs. So I use sharedUserId in both apps and the problem was solved:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test"
android:sharedUserId="test.account"
android:versionCode="100"
android:versionName="1.0" >
Find the well written article Write your own Android Authenticator

Amazon In-app purchase

has anybody tried implementing amazon's in-app purchase? I'm having problem implementing the example on their site. below example, it's giving me INVALID_SKU response:
when purchase is initiated,
PurchasingManager.initiateItemDataRequest("DeveloperSKU-1234");
the response of above will be recieved by below code:
public void onPurchaseResponse(final PurchaseResponse purchaseResponse) {
Log.v(TAG, "onPurchaseResponse recieved");
Log.v(TAG, "PurchaseRequestStatus:" + purchaseResponse.getPurchaseRequestStatus());
}
unfortunately, i always got "PurchaseRequestStatus:INVALID_SKU".
any of you knows how to make this work or do you know a good site for the tutorial?
Also at their site, dialog box should show if I got an INVALID_SKU which I didnt get any.
Here's how I got the In App purchases to work on Kindle Fire (after several hrs of struggle...)
adb install AmazonSDKTester.apk (Install SDKTester on Kindle Fire)
Create a file amazon.sdktester.json in the SDCARD directory (The connected KF shows up as SDCARD in Finder on ur Mac)
Contents of amazon.sdktester.json - {
"com.yourcompany.yourpkgname.200_coins" : {
"itemType": "CONSUMABLE",
"price": 0.99,
"title": "200 COINS",
"description": "2 COINS",
"smallIconUrl": "http://www.yourcompany.com/icon.png"
}
}
Press the power button on KF & press "Disconnect" button - Now KF is no longer a mounted drive on ur Mac.
Run the AmazonSDKTester app on KF.
Run your app from Eclipse. Make sure the package name in the JSON matches the In App Item package name on Amazon's website & in the PurchasingManager.initiatePurchaseRequest("com.yourcompany.yourpkgname.200_coins");
Now you should see the In App interstitials showing up.
Still doesn't work - Force Close both ur app & AmazonSDKTester on KF; Hard Reset KF ; Restart Eclipse & Restart from Step 1
INVALID_SKU occurs when SKU is not matching or not entered in JSON file. If you are implementing your test app using SDK Tester, then please make sure that the SKU which you are using in your app must have an entry in JSON file too. JSON files resides under /mnt/sdcard/ with name amazon.sdktester.json. Request you to verify whether you have created JSON file with SKU details under this path in the device.
A good approach for managing SKUs would be:
Reference SKUs as strings in your app's strings.xml file -- the same way you would use any string constant.
You can test your app using SDK Tester and the amazon.sdktester.json file without doing anything on the Developer Portal.
When you're ready to submit your app (after testing with SDKTester), make sure you have also submitted your IAP items on the Developer portal -- watch for typos!
We recommend using . for a SKU format, just because it makes it obvious what it is and what app it belongs to. For example:
com.yoyodyne.beachblanketbingo.500_coins

Categories

Resources