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.
Related
What we are dealing with
We have this app which we distribute to our clients in an offline fashion (i.e. not uploaded to Play store). The app flavour distributed to each client is almost identical with a bit of tweak here and there. All our clients share this app to their employees for usage. Basically this is an Enterprise App.
What's the problem
Recently one of our client started using a MDM (Mobility Device management) tool which blocks apps which are not downloaded from Google play. As obviously we got a request from our client to see if we can upload this app on Google play or not.
Important thing here is that we have over 100 clients and the package name of the app provided to each client is actually the same. So it's the same app with a bit of tweak here and there. If we go down the road of publishing the app to the play store, we might end up in a mayhem (we don't wanna upload 100 different apps to the play store - i.e. one for each client). We are doing some optimisation from our end so that multiple clients can use the same app (but we can't make all 100+ clients use the same app.).
What am I looking at ?
I started looking at Android For Work (AFW), Google private apps , Managed Google play and still digesting the stuffs. But to me it looked like just a secure way for enterprises to deploy/publish apps which can be downloaded only on specific devices and under a certain profile (which keeps things separate from user's personal apps and data in case they use the same phone for personal and work purpose).
What solution i am looking for ?
To privately deploy an app (host it with Google or privately host
but listed with Google play in both cases) and let my clients share
this app with their employee.
Each private app for each client should be on its own little
private island. I want to distribute the app with the same package
name to all my clients (From what I have read so far, this might not
be possible with Google play. But I am hoping somebody can point out
facts if I am missing something).
This is my solution:
Creating run-time dynamic app that get data and configs from back-end and render its views and data with its own Client Id.
You can create single app and upload to google play, but you should manage your clients by clientId that makes every app acts separated. This clientId is unique and generated per your clients. This solution have two sides. Android side and server side.
1 - Android side: Our app should have a baseUrl like this in Constants:
baseUrl = "http://yourCorporation.com/{clienId}/api/"
And then all the services of All clients use the same url. clientId is the key point. The difference of you client app is clientId. For generating url of api-call you should do something like this:
Constant.ClientId = scannedQRCode;
url = baseUrl.replace("{client_id}",Contant.ClientId) + apiUrl ;
You must create QR code per your clients that should scanned in app first run. It is good to send QR code after registration to his/her (client of your Clients) email. This QR code have clientId. Therefor every clients have their own services and really works as separated islands, even if you want to change server address, you can put all baseUrl in QR code but this is not suggested, because you have to create server per clients and this is headache.
You can even handle config and UI elements of you app with calling a config api that returns a customConfigDto as json like this:
public class CustomConfigDto {
String colorPrimary ;
String colroPrimaryDark ;
String colorAccent ;
int tabCounts;
//and more...
public String getColorPrimary() {
return colorPrimary;
}
public void setColorPrimary(String colorPrimary) {
this.colorPrimary = colorPrimary;
}
public String getColroPrimaryDark() {
return colroPrimaryDark;
}
public void setColroPrimaryDark(String colroPrimaryDark) {
this.colroPrimaryDark = colroPrimaryDark;
}
public String getColorAccent() {
return colorAccent;
}
public void setColorAccent(String colorAccent) {
this.colorAccent = colorAccent;
}
public int getTabCounts() {
return tabCounts;
}
public void setTabCounts(int tabCounts) {
this.tabCounts = tabCounts;
}
}
And render your views by this configurations. All of this works separated per app by their clientId.
I prefer QR code because it is very handy and classy and fit in your case, however you can enter this clientId with many other ways. This is one of best free and simple QR code generating service, and this is one of best QR-code scanner library for android.
2 - Server Side: You have to handle step1 in server-side and it is very easy. You can have entity calls Client that all other entities have it. Because you should keep all of your data in one place but separated by your clients. You can also map APIs like this in Spring:
#RequestMapping(value = "http://yourCorporation.com/{clienId}/api/customers", method = RequestMethod.GET)
Customers getCustomers(#PathVariable("clienId") Long clientId) {
return customerService.findCustomerByClientId(clientId);
}
Based on what you've said, this sounds more like you can solve this with configuration management than sending each client completely separate APKs.
Google has a private channel, but based on the documentation it seems much more oriented towards having a single membership list (i.e. once you're granted access you have access to the entire private channel) rather than highly customized access (i.e. certain people have access to certain items in the channel).
An alternative that I suggest: have all clients download the same APK. Give each of them a client-specific "activation code" for your app. When the app starts for the first time, it calls a web service and passes it its activation code; on the server side, you use the Activation Code to identify the client and then return data on the correct configuration to the client. Then you can distribute the same APK to everyone on your private channel and configure it remotely once it's installed.
A major advantage of this scheme is that you can have multiple configurations for an organization. Just give the client a choice of several activation codes, each of which will give them a certain configuration. For example, if you have an app that's used by both dock workers and janitors (and I'm just throwing out an example here), you could give the dock workers one activation code and janitors a second activation code and you can then easily give them different configurations.
Google Play now allows a developer to publish an app privately to up to 20 Managed Play organizations (or enterprises). To do so (instructions copied from the help center):
Sign in to the Google Play Console.
Go to Pricing & Distribution > User programs > Managed Google Play.
Check the Turn on advanced managed Google Play features box.
Check the Privately target this app to a list of organizations box.
Click Choose Organizations.
For each organization that you want to publish the app to, enter the Organization ID and a description (or name) and click Add. You can enter up to 20 organizations per app.
The good, long solution:
don't use the same package name for different apps. Create a multimodule project, set one module for the core, shared stuff, and add a module for each client where you can tweak what you need and configurate the package name dynamically based on build type. That way you can use the same package name for your CI server and everything else and have another package name when releasing the app.
The short workaround that may work:
Publish the app as a closed google play beta, and send invitations only to this client. That way he can distribute the app to his employees through play store and the other clients won't notice I can't assure it will work not knowing which MDM tool you are facing, but since beta channel apps don't require unknow origins permissions, you should be fine.
If you want the same package name, you'll have to do something like what EJoshuaS suggested: manage the different configurations inside of one app version. You won't be able to have more than one app with the same package deployed on Google Play.
If you're open to having different packages, you could just change the package name in the Android Manifest for each one and release as a different app. You would need to change the package everywhere you import the R file and you would need to make sure that all class references in your Manifest include the entire class path (<activity android:name="[full.package].MainActivity"> rather than <activity android:name=".MainActivity">). This gets pretty confusing and is terrible in terms of configuration management, so it's not really a great solution in general, but it might work for you.
I started looking at Android For Work (AFW), Google private apps , Managed Google play and still digesting the stuffs.
This would probably be a good fit for AFW.
But to me it looked like just a secure way for enterprises to deploy/publish apps which can be downloaded only on specific devices and under a certain profile
That's what an MDM does, yes, but there's more to it. With Android for Work you also have Managed Configurations which let you pass in a configuration for the app. This can be used to change backend urls, etc.
It for sure supports your second requirement, but I know too little to be certain about the first. While you can privately host and rollout an app on Google Play for Work, I don't know about distributing it privately to multiple clients.
The obvious benefit of using this Google API is that you don't have to build anything yourself. Also most MDMs support those Android for Work APIs, so that a domain admin can buy the app in bulk and distribute them to the employees. Have a look at the AppConfig Community which shows MDM Providers that incorporated those APIs and best practices.
Whatever you decide, you should definitely have a good look at Android for Work as what you are describing is exactly what it is intended for. The initial setup is a pain and there is way too little information about how it all works and plays together, but spending a few days trying to figure it out might be better than just building your own managed solution which you then will have to maintain too.
friends I am new in mirrorlink common Api.I don't know to enable mirror link service in android application.Please anyone tell me steps and any tutorial link.
I already do following things :-
I get developer account from mirrorlink.com.
I attached certificate with my app(that get from software that available from https://causeway.carconnectivity.org) Documents.
I saved device EMI number in my ACMS account (https://acms.carconnectivity.org)
Now I know I missing mirror link code for launching and terminate all this code and permission in manifest file.
Actually, I don't know how to code in the application for mirrorlink. please help me for step no.4
The launch and terminate UPnP code should be placed in the MainActivity. For certification purposes, your app needs to handle the Terminate intent without coming to the foreground (if it is in the background). Even if you don't respond to the intents, the app should be usable in MirrorLink.
You don't need to do anything extra to enable framebuffer streaming, or audio streaming. (Though providing context information via IContextManager.setFramebufferContextInformation and IContextManager.setAudioContextInformation is needed to make sure that the head unit knows what is being provided to it.)
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)
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.
I need to fetch some data over the cloud from my app. I've watched the google IO video on RESTful android apps # http://www.youtube.com/watch?v=xHXn3Kg2IQE&t=43m58s It recommends in the final slides to use a SyncAdapter to integrate with the Android System.
Later I learned that one has to use an Account to implement SyncAdapter. My app does not use an account. Users can freely download data without registration. Can I still use SyncAdapter? Is there a stock dummy account that I could use?
Edit: I do have a content provider for my app so that's not a problem
Edit2: I've just looked at the Weather and Stock apps under Settings -> Accounts & Sync. You can see that they allow syncing, but don't have a remove account button. On the other hand, Google, Facebook and Skype apps allow syncing PLUS they have a remove account button. This means Weather and Stock don't use accounts, whereas Google, Facebook and Skype do.
The tutorials I found # http://ericmiles.wordpress.com/2010/09/22/connecting-the-dots-with-android-syncadapter/ and # http://www.c99.org/2010/01/23/writing-an-android-sync-provider-part-1/ say that one MUST have an account to use Sync Adapter. :S ???
As the Android Developer docs say
Even if your app doesn't use accounts, you still need to provide an authenticator component. If you don't use accounts or server login, the information handled by the authenticator is ignored, so you can provide an authenticator component that contains stub method implementations. You also need to provide a bound Service that allows the sync adapter framework to call the authenticator's methods.
There is an entire article on Creating a Stub Authenticator. I realise that this question is old and an answer was accepted long ago, but I felt that a recent addition to the official docs should be included here.
I have created a contact sync adapter where I don't have a account authorization and or configuration screens. It wasn't that hard. I don't think having to deal with the Android Account stuff was that much of a deal.
Quote from your tutorial link:
The bad news is that there is no
“stock” functionality to give you an
easy way to provide an Account to the
system. However, in the same Sync
Adapter Example that comes with the
SDK there is a lot of code you can
borrow to give you Account
functionality. Unless you desire a
custom credentials screen, you can
heist all the code in the
com.example.android.samplesync.authenticator
package with only a few minor changes.
So it's basically just a copy and paste from the example, that's pretty much what I did and it worked fine.
I don't know for sure but all the adapters that don't have "Remove Account" seems to be built-in ROM adapters on all the devices I've looked at. I'm not sure you have to worried about it.
I keep getting lots of notifications from this question, so I thought I'll share this info. This is how you add SyncAdapter without Account. You can put this in onCreate of MyApplication extends Application class. This assumes you already have a SyncAdapter and ContentProvider implemented. You can do that by following the tutorials listed in the question.
final String ACCOUNT_NAME = "MyApp";
final String ACCOUNT_TYPE = "com.myapp.account";
final String PROVIDER = "com.myapp.provider";
Account appAccount = new Account(ACCOUNT_NAME,ACCOUNT_TYPE);
AccountManager accountManager = AccountManager.get(getApplicationContext());
if (accountManager.addAccountExplicitly(appAccount, null, null)) {
ContentResolver.setIsSyncable(appAccount, PROVIDER, 1);
ContentResolver.setMasterSyncAutomatically(true);
ContentResolver.setSyncAutomatically(appAccount, PROVIDER, true);
}
res/xml/syncadapter.xml
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="#string/provider"
android:accountType="#string/account_type"
android:userVisible="true"
android:supportsUploading="true"
/>
res/xml/authenticator.xml
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="#string/account_type"
android:icon="#drawable/app_icon"
android:smallIcon="#drawable/app_icon"
android:label="#string/app_label"
/>