How to check if an android device has Google Play installed? - android

I am trying to check if the device has Google Play installed or not in my app, but seems there is no way to do that. I followed the post HERE but still doesn't work, always return true even i was testing with an emulator, it has com.android.vending installed. So am i checking the wrong package name? Any ideas for that?
Thanks in advance!

Follow Dcoumentation to check if the device has Google Play Service available.
In Short, simply:
// Getting status
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getBaseContext());
// Showing status
if(status==ConnectionResult.SUCCESS)
//Google Play Services are available
else{
//Google Play Services are not available
}
Hope this will help you :)

Finally, found a way to check Google Play installed, here is the code:
public static boolean isPackageInstalled(Context context) {
PackageManager pm = context.getPackageManager();
boolean app_installed = false;
try {
PackageInfo info = pm.getPackageInfo("com.android.vending", PackageManager.GET_ACTIVITIES);
String label = (String) info.applicationInfo.loadLabel(pm);
app_installed = (!TextUtils.isEmpty(label) && label.startsWith("Google Play"));
} catch(PackageManager.NameNotFoundException e) {
app_installed = false;
}
return app_installed;
}

Related

Detect user using fake GPS Using isMockProvider [duplicate]

I will block a user from using my app if they fake the location.
So I use isFromMockProvider to check if the location is fake (follow here). But isFromMockProvider() may return false for faked locations in some cases.
public void onLocationChanged(Location location) {
textView.append("long:"+location.getLatitude()+" - lat:"+location.getLongitude()+" - isMock :"+location.isFromMockProvider() + "\n");
}
My case is: I use app Fake GPS location for fake to a location then I disable fake location and go to my app. Then the onLocationChanged returns the fake location with isFromMockProvider() = false
Video recorder: https://www.youtube.com/watch?v=rWVvjOCaZiI (in this video, my current location is 16.06, 108.21, the fake location is 36.26,138.28. You can see in last video the location is 36.26,138.28 but isFromMockProvider=false)
Is there any way to detect if a user uses a fake location in this case? Any help or suggestion would be great appreciated.
DEMO project
Risking a Realistic Answer
I'd like to provide an answer that helps the developer understand the public relations aspect of product design, taking the risk of criticism. Frankly, one cannot write great apps in a computer science vacuum. Satisfying user needs and balancing them with security is one of the primary issues in software interface and behavioral design today, especially in the mobile space.
From this perspective, your question, "Is there any way to detect if a user uses a fake location in this case?" may not be the most pertinent question you face. I'm not being evasive by asking this other question that may help you more and it is something I can answer well: "Is there any way to securely get the data from the user's device's geocoordinate firmware such that it cannot be spoofed?"
The answer to this one is, "No."
Android HTTP Client Contract
It is not part of the Android client-server contract or that of its competitors to guarantee user device location information.
Practical Reason
There is actually a market force that will probably push against such a guarantee indefinitely. Many device owners (and your users) want control over whether people know their true location for privacy and home and family security reasons.
Solution
The next question you can ask yourself as a designer of your software is, "How can the app or library work and provide for the needs I seek to fill with a certain percentage of the user community using today's (or tomorrow's) location spoofing software?"
If you are writing business intelligence software or there is some other statistical aspect to your system, then you need the software equivalent of error bars. If you display the stats, then the error bars would be an appropriate graphing feature. Estimating the percentage of location spoofers out of a population of users would require further study.
I use two ways to identify fake locations.
First, i check mock location, like in other code here.
public static boolean isMockLocationOn(Location location, Context context) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
return location.isFromMockProvider();
} else {
String mockLocation = "0";
try {
mockLocation = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION);
} catch (Exception e) {
e.printStackTrace();
}
return !mockLocation.equals("0");
}
}
Second, i check running apps and services, that need permission to access mock location.
public static List<String> getListOfFakeLocationApps(Context context) {
List<String> runningApps = getRunningApps(context);
List<String> fakeApps = new ArrayList<>();
for (String app : runningApps) {
if(!isSystemPackage(context, app) && hasAppPermission(context, app, "android.permission.ACCESS_MOCK_LOCATION")){
fakeApps.add(getApplicationName(context, app));
}
}
return fakeApps;
}
public static List<String> getRunningApps(Context context, boolean includeSystem) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
HashSet<String> runningApps = new HashSet<>();
try {
List<ActivityManager.RunningAppProcessInfo> runAppsList = activityManager.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo processInfo : runAppsList) {
runningApps.addAll(Arrays.asList(processInfo.pkgList));
}
} catch (Exception ex) {
ex.printStackTrace();
}
try {
//can throw securityException at api<18 (maybe need "android.permission.GET_TASKS")
List<ActivityManager.RunningTaskInfo> runningTasks = activityManager.getRunningTasks(1000);
for (ActivityManager.RunningTaskInfo taskInfo : runningTasks) {
runningApps.add(taskInfo.topActivity.getPackageName());
}
} catch (Exception ex) {
ex.printStackTrace();
}
try {
List<ActivityManager.RunningServiceInfo> runningServices = activityManager.getRunningServices(1000);
for (ActivityManager.RunningServiceInfo serviceInfo : runningServices) {
runningApps.add(serviceInfo.service.getPackageName());
}
} catch (Exception ex) {
ex.printStackTrace();
}
return new ArrayList<>(runningApps);
}
public static boolean isSystemPackage(Context context, String app){
PackageManager packageManager = context.getPackageManager();
try {
PackageInfo pkgInfo = packageManager.getPackageInfo(app, 0);
return (pkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return false;
}
public static boolean hasAppPermission(Context context, String app, String permission){
PackageManager packageManager = context.getPackageManager();
PackageInfo packageInfo;
try {
packageInfo = packageManager.getPackageInfo(app, PackageManager.GET_PERMISSIONS);
if(packageInfo.requestedPermissions!= null){
for (String requestedPermission : packageInfo.requestedPermissions) {
if (requestedPermission.equals(permission)) {
return true;
}
}
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return false;
}
public static String getApplicationName(Context context, String packageName) {
String appName = packageName;
PackageManager packageManager = context.getPackageManager();
try {
appName = packageManager.getApplicationLabel(packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA)).toString();
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return appName;
}
(Update)
Unfortunately, google forbid applications from receiving the list of currently running apps.
(It was since 5.1.1, but i still can get app list in test devices runned android 7.1)
Now you can get only list of recently used apps (with request runtime permission for it) by using UsageStatsManager, for example like here Android 5.1.1 and above - getRunningAppProcesses() returns my application package only
So if user close or exit from fake location app, i can't determinate it.
And now, to get list of fake location apps, i try to get locations, and if location.isFromMockProvider() return true, i scan device for all installed apps, that need permission to access mock location like this:
public static List<String> getListOfFakeLocationAppsFromAll(Context context) {
List<String> fakeApps = new ArrayList<>();
List<ApplicationInfo> packages = context.getPackageManager().getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo aPackage : packages) {
boolean isSystemPackage = ((aPackage.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
if(!isSystemPackage && hasAppPermission(context, aPackage.packageName, "android.permission.ACCESS_MOCK_LOCATION")){
fakeApps.add(getApplicationName(context, aPackage.packageName));
}
}
return fakeApps;
}
Answers on This SO question and to a lesser extent the answers on This SO question seem to indicate you are suffering from an unfortunate Caching issue in the FusedLocationApi caused by onLocationChanged being called with an out of date timestamp (thus ignoring the result as it thinks there is already newer data).
To quote Reno's answer:
Unless you have not changed ... so that new APs can be discovered, I'm afraid you will get only cached locations. If you want fresh locations use the GPS provider.
The solution will be to instead call a location from the GPS Provider like so:
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationListener locationListener = new MyLocationListener();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 10, locationListener);
(The code above comes from a longer example here)
I use this method in my projects and it work perfectly till now:
for api < 18
//returns true if mock location enabled, false if not enabled.
public static boolean isMockLocationOn(Context context) {
if (Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0"))
return false;
else
return true;
}
For api >= 18 you should use
location.isFromMockProvider();
The point is location.isFromMockProvider is buggy and some times it will show a mocked location as its OK !!!
There is a workaround in this link with full detail
Location on Android: Stop Mocking Me!
the approach is :
Remember the most recent location labeled as a mock
If a new “non-mock” reading is within 1km of the last mock, reject
it.
Only clear the last mock location after 20 consecutive “non-mock”
readings.

Check whether whatsapp installed or not for particular mobile number

how to check whether user has whatsapp installed or not???
I want app like whenever I click on users number it should display message whether that user has whatsapp or not...
please help me.I have listview of contacts info means name and number..I want to check whether that particular number has whatsapp installed or not on click of listview item????
Use packagemanager to get the installed app info:
for whatsapp package name is com.whatsapp
boolean installed = appInstalledOrNot("com.whatsapp"); //the method returns boolean value here
private boolean appInstalledOrNot(String uri) {
PackageManager pm = getPackageManager();
boolean app_installed;
try {
pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
app_installed = true;
}
catch (PackageManager.NameNotFoundException e) {
app_installed = false;
}
return app_installed;
}
public static boolean isInstalled(String packageName) {
if (StringUtils.equalsNull(packageName)) {
return false;
}
PackageManager pm = ContextProvider.getApplicationContext()
.getPackageManager();
List<PackageInfo> list = pm
.getInstalledPackages(PackageManager.PERMISSION_GRANTED);
for (PackageInfo p : list) {
if (packageName.equals(p.packageName)) {
return true;
}
}
return false;
}

What is the minimum version code of Google Play Services that supports GCM Network Manager?

I want to use GCM Network Manager in my application. This library needs Google Play Service version 7.5 and above installed on user's device. I want to check that if Google Play Services is installed and its version is above 7.5. I did as below:
private boolean isGcmNetworkManagerAvailable(Context context) {
final int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(context);
if (status != ConnectionResult.SUCCESS) {
return false;
}
final String gpsPackageName = GooglePlayServicesUtil.GOOGLE_PLAY_SERVICES_PACKAGE;
PackageManager pm = context.getPackageManager();
try {
PackageInfo gpsPackageInfo = pm.getPackageInfo(gpsPackageName,0);
int versionCode = gpsPackageInfo.versionCode;
//
// What is the version code of Google Play Services version 7.5?
//
if(versionCode < GOOGLE_PLAY_SERVICES_7_5_VERSION_CODE) {
return false;
}
} catch (PackageManager.NameNotFoundException e) {
return false;
}
return true;
}
Problem is that I don't know the exact version code of Google Play Services version 7.5 to check in this method.
Based on this answer version code of google Play Services is simply a 7-digit number created from its version code so version 7.5 has 7500000 version code.
Hope this will help
/**
* Check the device to make sure it has the Google Play Services APK. If
* it doesn't, display a dialog that allows users to download the APK from
* the Google Play Store or enable it in the device's system settings.
*/
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
}
return false;
}
return true;
}

Does every android phone has streetview application by default?

Does every android phone with 2.3 and above has streetview by default or one have to download the streetview and install it. The reason I am asking is that I am using streetview in my application and I use
private boolean isIntentAvailable(Intent intent) {
final PackageManager packageManager = mapView.getContext().getPackageManager();
List<ResolveInfo> list =
packageManager.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}
to see if streetview application is available in the device. The problem is that in one of mobile with android 4.1.1 streetview is available but still this method throws false for that. But it works in most of the devices that I have tested like in all Samsung , HTC and sony mobiles.
Not all android devices have Google apps. It depends of the constructor
[EDIT :]
to check if an app is installed, you may use :
appInstalledOrNot("com.google.android.apps.maps")
using the method:
private boolean appInstalledOrNot(String uri) {
PackageManager pm = getPackageManager();
boolean app_installed = false;
try {
pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
app_installed = true;
} catch (PackageManager.NameNotFoundException e) {
app_installed = false;
}
return app_installed ;
}
I read somewhere that all version of Maps have Street View, but I really can not confirm this, I am not sure.

Determine that android package is preinstalled by vendor

I wonder whether there is a way to know that my app is preinstalled by vendor (and not installed from Android Market). Application is also available in Android Market and can be updated from there.
One solution is to create a file in the local file system (we can build a special app version for vendor). But there is a case that application can be updated from the market before its first run, and file is not created.
So is there any other way? Probably, installation path?
Also it's interesting whether Android Market app checks this preinstalled app for updates automatically like it's performed for Google Maps.
You have to get the ApplicationInfo of your package (with the PackageManager) and then check its flags.
import android.content.pm.ApplicationInfo;
if ((ApplicationInfo.FLAG_SYSTEM & myApplicationInfo.flags) != 0)
// It is a pre embedded application on the device.
For a more complete example, one could use this:
private String getAllPreInstalledApplications() {
String allPreInstalledApplications = "";
PackageManager pm = getPackageManager();
List<ApplicationInfo> installedApplications = pm
.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo applicationInfo : installedApplications) {
if (isApplicationPreInstalled(applicationInfo)) {
allPreInstalledApplications += applicationInfo.processName + "\n";
}
}
return allPreInstalledApplications;
}
private static boolean isApplicationPreInstalled(ApplicationInfo applicationInfo) {
if (applicationInfo != null) {
int allTheFlagsInHex = Integer.valueOf(
String.valueOf(applicationInfo.flags), 16);
/*
If flags is an uneven number, then it
is a preinstalled application, because in that case
ApplicationInfo.FLAG_SYSTEM ( == 0x00000001 )
is added to flags
*/
if ((allTheFlagsInHex % 2) != 0) {
return true;
}
}
return false;
}

Categories

Resources