/*
* Copyright (c) 2012 Socialize Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.socialize.util;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.telephony.TelephonyManager;
import com.socialize.Socialize;
import com.socialize.SocializeService;
import com.socialize.auth.facebook.FacebookActivity;
import com.socialize.config.SocializeConfig;
import com.socialize.log.SocializeLogger;
import com.socialize.ui.SocializeLaunchActivity;
import com.socialize.ui.action.ActionDetailActivity;
import com.socialize.ui.comment.CommentActivity;
import com.socialize.ui.profile.ProfileActivity;
import java.util.List;
import java.util.Locale;
/**
* @author Jason Polites
*/
public class DefaultAppUtils implements AppUtils {
private String packageName;
private String appName;
private String userAgent;
private String country;
private String carrier = "unknown";
private String networkType = "unknown";
private SocializeLogger logger;
private SocializeConfig config;
private boolean locationAvailable = false;
private boolean locationAssessed = false;
private boolean notificationsAvailable = false;
private boolean notificationsAssessed = false;
private String lastNotificationWarning = null;
public void init(Context context) {
packageName = context.getPackageName();
// Try to get the app name
try {
PackageManager pkgManager = context.getPackageManager();
appName = pkgManager.getApplicationLabel(pkgManager.getApplicationInfo(packageName, 0)).toString();
}
catch (Exception e) {
String msg = "Failed to lookup application label. Make sure this is specified in your AndroidManifest.xml";
if(logger != null) {
logger.error(msg, e);
}
else {
SocializeLogger.e(msg, e);
}
}
if(StringUtils.isEmpty(appName)) {
appName = packageName;
}
if(StringUtils.isEmpty(appName)) {
appName = "A Socialize enabled app";
}
try {
if(hasPermission(context, "android.permission.READ_PHONE_STATE")) {
TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
country = manager.getNetworkCountryIso();
carrier = manager.getNetworkOperatorName();
if(StringUtils.isEmpty(carrier)) {
carrier = "unknown";
}
}
}
catch (Exception ignore) {}
if(StringUtils.isEmpty(country)) {
country = Locale.getDefault().getCountry();
}
}
@Override
public void onResume(Context context) {
determineNetworkType(context);
}
private void determineNetworkType(Context context) {
try {
if(hasPermission(context, "android.permission.ACCESS_NETWORK_STATE")) {
ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if(mWifi != null && mWifi.isConnected()) {
networkType = "wifi";
}
else {
networkType = "cell";
}
}
}
catch (Exception ignore) {}
}
@Override
public String getAppStoreAbbreviation(String appStore) {
if(appStore != null && appStore.equalsIgnoreCase("amazon")) {
return "amz";
}
return null;
}
@Override
public boolean isActivityAvailable(Context context, String activityClassName) {
try {
Class<?> activityClass = Class.forName(activityClassName);
return isActivityAvailable(context, activityClass);
}
catch (ClassNotFoundException ignored) {}
return false;
}
/* (non-Javadoc)
* @see com.socialize.util.IAppUtils#isActivityAvailable(android.content.Context, java.lang.Class)
*/
@Override
public boolean isActivityAvailable(Context context, Class<?> activity) {
Intent intent = new Intent(context, activity);
return isIntentAvailable(context, intent);
}
/* (non-Javadoc)
* @see com.socialize.util.IAppUtils#isIntentAvailable(android.content.Context, java.lang.String)
*/
@Override
public boolean isIntentAvailable(Context context, String action) {
Intent intent = new Intent(action);
return isIntentAvailable(context, intent);
}
/* (non-Javadoc)
* @see com.socialize.util.IAppUtils#isIntentAvailable(android.content.Context, android.content.Intent)
*/
@Override
public boolean isIntentAvailable(Context context, Intent intent) {
PackageManager packageManager = context.getPackageManager();
return packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
/* (non-Javadoc)
* @see com.socialize.util.IAppUtils#isServiceAvailable(android.content.Context, java.lang.Class)
*/
@Override
public boolean isServiceAvailable(Context context, Class<?> cls) {
final PackageManager packageManager = context.getPackageManager();
final Intent intent = new Intent(context, cls);
return packageManager.queryIntentServices(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
@Override
public ActivityInfo getActivityInfo(Context context, Class<?> cls) {
try {
final PackageManager packageManager = context.getPackageManager();
return packageManager.getActivityInfo(new ComponentName(context, cls), 0);
}
catch (NameNotFoundException e) {
if(logger != null) {
logger.error("Failed to locate info for activity [" +
cls.getName() +
"]", e);
}
else {
SocializeLogger.e(e.getMessage(), e);
}
}
return null;
}
/* (non-Javadoc)
* @see com.socialize.util.IAppUtils#isReceiverAvailable(android.content.Context, java.lang.Class)
*/
@Override
public boolean isReceiverAvailable(Context context, Class<?> cls) {
final PackageManager packageManager = context.getPackageManager();
final Intent intent = new Intent(context, cls);
return packageManager.queryBroadcastReceivers(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
/* (non-Javadoc)
* @see com.socialize.util.IAppUtils#isLocationAvaiable(android.content.Context)
*/
@Override
public boolean isLocationAvailable(Context context) {
if(!locationAssessed && config != null) {
locationAvailable = config.getBooleanProperty(SocializeConfig.SOCIALIZE_LOCATION_ENABLED, true) && (hasPermission(context, "android.permission.ACCESS_FINE_LOCATION") || hasPermission(context, "android.permission.ACCESS_COARSE_LOCATION"));
locationAssessed = true;
}
return locationAvailable;
}
/* (non-Javadoc)
* @see com.socialize.util.IAppUtils#isNotificationsAvaiable(android.content.Context)
*/
@Override
public boolean isNotificationsAvailable(Context context) {
if(!notificationsAssessed) {
String permissionString = context.getPackageName() + ".permission.C2D_MESSAGE";
boolean ok = true;
if(config.getBooleanProperty(SocializeConfig.SOCIALIZE_NOTIFICATIONS_ENABLED, true)) {
if(!hasPermission(context, permissionString)) {
lastNotificationWarning = "Notifications not available, permission [" + permissionString + "] not specified in AndroidManifest.xml";
if(logger.isInfoEnabled()) logger.info(lastNotificationWarning);
ok = false;
}
if(!hasPermission(context, "com.google.android.c2dm.permission.RECEIVE")) {
lastNotificationWarning = "Notifications not available, permission com.google.android.c2dm.permission.RECEIVE not specified in AndroidManifest.xml, or device does not include Google APIs";
if(logger.isInfoEnabled()) logger.info(lastNotificationWarning);
ok = false;
}
if(config.isEntityLoaderCheckEnabled() && getSocialize().getEntityLoader() == null) {
lastNotificationWarning = "Notifications not available. Entity loader not found.";
if(logger.isInfoEnabled()) logger.info(lastNotificationWarning);
ok = false;
}
}
else {
ok = false;
if(logger.isDebugEnabled()) {
logger.debug("SmartAlerts disabled in config");
}
}
notificationsAvailable = ok;
notificationsAssessed = true;
}
else if(!notificationsAvailable) {
if(lastNotificationWarning != null && logger.isInfoEnabled()) {
logger.info(lastNotificationWarning);
}
}
return notificationsAvailable;
}
protected SocializeService getSocialize() {
return Socialize.getSocialize();
}
@Override
public void checkAndroidManifest(Context context) {
// Check the launch activity config
checkActivitiesExist(context, CommentActivity.class, ActionDetailActivity.class, ProfileActivity.class, FacebookActivity.class, SocializeLaunchActivity.class);
ActivityInfo info = getActivityInfo(context, SocializeLaunchActivity.class);
if(info != null) {
if((info.flags & ActivityInfo.FLAG_NO_HISTORY) != ActivityInfo.FLAG_NO_HISTORY) {
logger.warn("Activity flag android:noHistory=\"true\" not found for " + SocializeLaunchActivity.class.getSimpleName() + ". Please ensure this is added to the declaration of this activity in your AndroidManifest.xml");
}
if((info.launchMode & ActivityInfo.LAUNCH_SINGLE_TOP) == ActivityInfo.LAUNCH_SINGLE_TOP) {
logger.warn("Activity flag android:launchMode=\"singleTop\" found for " + SocializeLaunchActivity.class.getSimpleName() + ". This should be removed from the declaration of this activity in your AndroidManifest.xml");
}
}
info = getActivityInfo(context, CommentActivity.class);
if(info != null) {
if((info.configChanges & ActivityInfo.CONFIG_ORIENTATION) != ActivityInfo.CONFIG_ORIENTATION) {
logger.warn("Activity flag android:configChanges=\"orientation|keyboardHidden|screenSize\" not found for " + CommentActivity.class.getSimpleName() + ". Please ensure this is added to the declaration of this activity in your AndroidManifest.xml");
}
}
}
protected void checkActivitiesExist(Context context, Class<?>...classes) {
for (Class<?> cls : classes) {
ActivityInfo info = getActivityInfo(context, cls);
if(info == null) {
logger.warn("No activity element declared for [" +
cls.getName() +
"]. Please ensure you have included this in your AndroidManifest.xml");
}
}
}
/* (non-Javadoc)
* @see com.socialize.util.IAppUtils#hasPermission(android.content.Context, java.lang.String)
*/
@Override
public boolean hasPermission(Context context, String permission) {
return context.getPackageManager().checkPermission(permission, context.getPackageName()) == PackageManager.PERMISSION_GRANTED;
}
public static boolean launchMainApp(Activity origin) {
Intent mainIntent = getMainAppIntent(origin);
if(mainIntent != null) {
origin.startActivity(mainIntent);
return true;
}
return false;
}
public static Intent getMainAppIntent(Context context) {
PackageManager pm = context.getPackageManager();
Intent mainIntent = new Intent(Intent.ACTION_MAIN);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
mainIntent.setPackage(context.getPackageName());
List<ResolveInfo> appList = pm.queryIntentActivities(mainIntent, 0);
if(appList != null && appList.size() > 0) {
ResolveInfo resolveInfo = appList.get(0);
mainIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mainIntent.setComponent(new ComponentName(resolveInfo.activityInfo.applicationInfo.packageName, resolveInfo.activityInfo.name));
return mainIntent;
}
return null;
}
/**
* Attempts to get the resource if for the app icon.
* @param context
* @return
*/
public int getAppIconId(Context context) {
ApplicationInfo applicationInfo = context.getApplicationInfo();
return applicationInfo.icon;
}
public String getUserAgentString() {
if (userAgent == null) {
userAgent = "Android-" + android.os.Build.VERSION.SDK_INT + "/" + android.os.Build.MODEL + " SocializeSDK/v" + Socialize.VERSION + "; " + Locale.getDefault().getLanguage() + "_"
+ getCountry() + "; BundleID/" + getPackageName() + "; Carrier/" + carrier + ";";
}
// Always add the network state in case it changed
return userAgent + " Network/" + networkType + ";";
}
/* (non-Javadoc)
* @see com.socialize.util.IAppUtils#getAppName()
*/
@Override
public String getAppName() {
return appName;
}
@Override
public String getCountry() {
return country;
}
@Override
public String getCarrier() {
return carrier;
}
@Override
public String getNetworkType() {
return networkType;
}
@Override
public String getPackageName() {
return packageName;
}
public void setLogger(SocializeLogger logger) {
this.logger = logger;
}
public void setConfig(SocializeConfig config) {
this.config = config;
}
void setNotificationsAssessed(boolean notificationsAssessed) {
this.notificationsAssessed = notificationsAssessed;
}
}