I have a Vision API Barcode scanner logic which is based on play-services-vision:17.0.2 to scan barcodes and QR codes. This is working on most phones apart for the users in the China region where play services and stores are disabled.
So, I need to find a way if Vision API is allowed or not and make a switch to either use full-fledged Vision API or fallback to the minimal feature of ZXing library.
For this, I tried googleApiAvailability.isGooglePlayServicesAvailable(activity)
and included com.google.android.gms:play-services-base:17.1.0.
However, after installing the app I am receiving a message that "to open the app Play services and Play store apps are required". How can I address this?
Is there any other way to find out and make the proper switch of features or maybe better ways to handle this?
Thank you...
I found this code snippet in another question and it helped me.
try {
packageManager.getPackageInfo("com.google.android.gms", 0);
// - >Installed
} catch (PackageManager.NameNotFoundException e) {
// -> Not installed
}
Related
I want to see analytics in my android application, but am struggling to set Adobe Launch and Analytics up.
I have Mobile Core and Analytics set up in the app itself. And it isn't producing any errors on run.
MobileCore.setApplication(this)
MobileCore.setLogLevel(LoggingMode.DEBUG)
try {
MobileServices.registerExtension()
Analytics.registerExtension()
Lifecycle.registerExtension()
MobileCore.start { MobileCore.configureWithAppID("app-id-here") }
} catch (e: Exception) {
// Log
}
And have created the property in Adobe Launch adding the relevant extensions needed, setting up environments and publishing a library. I now have a library published. But have no idea how to view the data gathered from the app? Am I miss understanding what Launch is? Any help on this would be appreciated.
Once registeration is done you can able to see the logs in App logs "AdobeExperienceSDK" but to see the actual event you need to login on AEP dashboard portal.
For setup and instruction please visit below official url from Adobe Launch
https://experienceleague.adobe.com/docs/launch-learn/implementing-in-mobile-android-apps-with-launch/configure-launch/launch-install-the-mobile-sdk.html?lang=en#prerequisites
I may be misunderstanding your question, but if you're asking how to see an aggregation of the data you sent to Adobe, your request contains the address of the repo where you're sending your info. You need to log into Adobe Analytics to see what you sent.
You need to set the events to track the screen views. Example:
Analytics.trackState("Screen Name", null);
The oficial documentation:
https://docs.adobe.com/content/help/en/mobile-services/android/analytics-android/states.html
You can also use https://aep-sdks.gitbook.io/docs/using-mobile-extensions/adobe-experience-platform-assurance , which can let you see Adobe Launch console/debugging notes in the Adobe Griffon interface. A bit overkill for a one-time thing, but if you're going to be spending a lot of time withLaunch in your app, it might be worth setting up.
I currently have code that gets the device identifier (advertising ID) on Google Play enabled and Kindle devices. Now I'm looking for documentation targeting developers that would explain how to get it on other Android forks (similar to Amazon's instructions), esp. on Xiaomi and Alibaba phones made for the local Chinese market.
One resource I could find is by AppsFlyer which is obviously bogus since it states "IMEI and Android ID - Both are necessary for accurate attribution" while the former is disabled since Android 6 (unless you want to prompt the user for a runtime permission) besides other problems with it and the latter is not device unique since Oreo.
Yes, IMEI, Mac address and Android ID are using for the Android market in China. Unity, Vungle and Admob are actually pursuing the Android market. We also heard that other ad networks create a custom Android SDK just for the Chinese market.
Last time I talked to a Chinese developer on the Android market in China was a while back so my info may be outdated. I'll double check tonight.
This isn't the answer I was hoping for, but after further research, the "first and largest independent mobile advertising platform of China", Youmi, does have an open source DeviceInfoUtils class and they do everything AppsFlyer recommended, that is, everything Google is against.
To be specific, with every request, they send: telephonyManager.getDeviceId(); (IMEI on GSM phones), telephonyManager.getSubscriberId() (IMSI on GSM phones), the MAC address, and the ANDROID_ID. Again, the first two of these require prompting the user for allowing the app to "make and manage phone calls" which is super creepy (resulting in bad app ratings and/or denied permissions). The latter two of these used to work but as of Oreo, they are not device unique any more as I mentioned in my question statement.
Update: I have now downloaded Xiaomi's Mimo SDK (ads SDK). Decompiling reveals a class called AdvertisingIdHelper which has only two methods, one to check if the device has Google Play store installed, and the other looks like this:
private static d z(Context paramContext)
{
if (!y(paramContext)) {
return null;
}
try {
d localD = new d();
Intent localIntent = new Intent("com.google.android.gms.ads.identifier.service.START");
localIntent.setPackage("com.google.android.gms");
if (paramContext.bindService(localIntent, localD, 1))
return localD;
} catch (SecurityException localSecurityException) {
com.miui.zeus.a.a.b("stacktrace_tag", "stackerror:", localSecurityException);
return null;
}
return null;
}
What its role is in the overall SDK is unclear but it definitely seems like a way of querying Google's ads ID rather than Xiaomi's alternative ID. If this is for all cases, or only for devices sold outside of China (which does have Google Play services) is again unclear.
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.
I wrote a Cordova application with a TTS provided by translation google REST services, that are no more available (from today I suppose) because they require a captcha to work. I have some questions about this:
- is possible to pay for the service? (Google translate API V2 don't seem the answer ...)?
- does Android text-to-speech work without internet?
- is there a Cordova plugin to connect this service?
- is it available something like this for iOS?
I will talk about the last question you asked. Yes there is offline TTS service for iOS. It's AVSpeechSynthesizer.
NSString *ttsString = #"Hello Bangladesh";
NSString *language = #"en-US";
AVSpeechSynthesizer *synth = [[AVSpeechSynthesizer alloc] init];
AVSpeechUtterance *utterance = [AVSpeechUtterance
speechUtteranceWithString:ttsString];
utterance.rate = 0.5f;
utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:language];
[synth speakUtterance:utterance];
You can see the list of language codes.
for(AVSpeechSynthesisVoice *voice in [AVSpeechSynthesisVoice speechVoices])
{
NSLog(#"%#", voice.language);
}
I wanted to make a comment but my reputation is not enough. You can use SpeechRecognizer. It supports offline TTS utility for couple of languages including English, but not for all.
Actually it is both online and offline. If device is connected to a network then it uses online recognition communicating with Google servers. If device is offline then it uses offline package which is installed on the device.
I've done some research (Stack Overflow and on the web) and see that there are some other questions about Google Goggles and the possibility of using it with Android; via an Intent. I realize it is not officially supported and that we are all still waiting for Google to open up the API or provide us the functionality to easily use it in our apps.
That said - I would still like an answer / some clarification on the following, if anyone can help?
Referencing this question: zxing intent "google goggles" doesn't recognize barcodes
It is answered that Google Goggles does decode barcodes, which indeed it does... so in my app I am calling to the latest version of the Google Goggles app via the IntentIntegrator:
https://code.google.com/p/zxing/wiki/ScanningViaIntent https://code.google.com/p/zxing/source/browse/trunk/android-integration/src/com/google/zxing/integration/android/IntentIntegrator.java
This call via the IntentIntegrator successfully opens Google Goggles in scan mode (of sorts), however there is no 'Capture' button displayed on the UI, it is hidden / unavailable ... so it is not possible to take a shot / capture any image, to see if the callback with result to my app works.
So my thoughts are:
This just isn't supported and the button is disabled because of the way I called to open Google Goggles?
I've done something wrong in the way that I am making the call?
The latest version of Google Goggles disables this functionality that used to be available in previous versions?
Other?
Code sample of how I'm making the call to open Google Goggles below. Also another way to do the same thing is included, but commented out for reference.
// Try and open Google Goggles for scanning
try{
IntentIntegrator integrator = new IntentIntegrator(getSupportActivity());
integrator.initiateScan(IntentIntegrator.TARGET_ALL_KNOWN);
//Intent intent = new Intent("com.google.zxing.client.android.SCAN");
//intent.setPackage("com.google.android.apps.unveil");
//startActivity(intent);
}catch(Exception e){
Log.e(ScanFragment.class.getName(), "onViewCreated > Error creating scan Intent to Google Goggles: " + e.getMessage());
}
//>
Any help on finding out more on this would be greatly appreciated; thanks.
// WildStyle
Yes, I am actually not sure Goggles supports this Intent anymore. It is not in the list of apps that will be targeted by default. So I don't think you are opening Goggles if you are using IntentIntegrator; you are opening one of the Barcode Scanner apps. They don't have a capture button, you just bring the barcode into view.
If it's really opening Goggles, maybe it was previously set as the default for this Intent and that is taking precedence. Try clearing application handler associations in Settings.