Open global search as overlay - android

I am writing a launcher and want to be able to open up a search as an overlay rather than full-screen in the Google App.
So far I only found a way to open the search in the Google App full-screen as follows (taken from AOSP Launcher3 source code):
public static boolean openSearch(Context context) {
SearchManager searchManager = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
ComponentName globalSearchActivity = searchManager.getGlobalSearchActivity();
if (globalSearchActivity == null) {
Timber.w("No global search activity found.");
return false;
}
Intent intent = new Intent(android.app.SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setComponent(globalSearchActivity);
Bundle appSearchData = new Bundle();
appSearchData.putString("source", "launcher-search");
intent.putExtra(android.app.SearchManager.APP_DATA, appSearchData);
intent.putExtra(android.app.SearchManager.QUERY, "");
intent.putExtra(android.app.SearchManager.EXTRA_SELECT_QUERY, true);
try {
context.startActivity(intent);
return true;
} catch (ActivityNotFoundException ex) {
Timber.w("Global search activity not found: %s", globalSearchActivity);
return false;
}
}
I know it is possible because other launchers like Nova and Action Launcher managed to do it...

Figured it out...
public static boolean showGlobalSearchOverlay(Context context) {
ComponentName globalSearchActivity =
new ComponentName("com.google.android.googlequicksearchbox",
"com.google.android.apps.gsa.queryentry.QueryEntryActivity");
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(globalSearchActivity);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
context.startActivity(intent);
return true;
} catch (Throwable e) {
Timber.w("Unable to show search overlay");
return false;
}
}

Related

Show recent apps programmatically on android oreo

I want to somehow immitate the recent apps hard button click which opens up the native android recent apps screen.
I do following currently:
boolean success = showRecents1(c);
if (!success) {
showRecents2(c);
}
This works on a lot of devices, but on the android oreo emulator it does not work. Does anyone know a solution that works on android oreo as well?
private boolean showRecents1(Context c) {
try {
Intent intent = new Intent("com.android.systemui.recent.action.TOGGLE_RECENTS");
intent.setComponent(new ComponentName("com.android.systemui", "com.android.systemui.recent.RecentsActivity"));
c.startActivity(intent);
return true;
} catch (Exception e) {
L.e(e);
}
return false;
}
private boolean showRecents2(Context c) {
try {
Class serviceManagerClass = Class.forName("android.os.ServiceManager");
Method getService = serviceManagerClass.getMethod("getService", String.class);
IBinder retbinder = (IBinder) getService.invoke(serviceManagerClass, "statusbar");
Class statusBarClass = Class.forName(retbinder.getInterfaceDescriptor());
Object statusBarObject = statusBarClass.getClasses()[0].getMethod("asInterface", IBinder.class).invoke(null, new Object[]{retbinder});
Method clearAll = statusBarClass.getMethod("toggleRecentApps");
clearAll.setAccessible(true);
clearAll.invoke(statusBarObject);
return true;
} catch (Exception e) {
L.e(e);
}
return false;
}

MultiWindow launcher android application for android 7.0 nougat

I am developing a android application as a launcher that will open another application in different window like Taskbar( https://play.google.com/store/apps/details?id=com.farmerbb.taskbar&hl=en) application.
I tried to open another application using component name and reflection method. Issue is when new application opens in another window , my launcher application get killed. How can i stop to kill my launcher application.
This is the code snippet for launching a new application in new window :
public void launchApplication(String componentName) {
ActivityOptions options = getActivityOptions(AppConstants.FREEFORM_WORKSPACE_STACK_ID);
Intent intent = new Intent();
intent.setComponent(ComponentName.unflattenFromString(componentName));
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
try {
startActivity(intent, options.toBundle());
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
public ActivityOptions getActivityOptions(int applicationType) {
ActivityOptions options = ActivityOptions.makeBasic();
Integer stackId = null;
switch (applicationType) {
case FULLSCREEN_WORKSPACE_STACK_ID:
stackId = FULLSCREEN_WORKSPACE_STACK_ID;
break;
case FREEFORM_WORKSPACE_STACK_ID:
stackId = FREEFORM_WORKSPACE_STACK_ID;
break;
case DOCKED_STACK_ID:
stackId = DOCKED_STACK_ID;
break;
}
if (stackId != null) {
try {
Method method = ActivityOptions.class.getMethod("setLaunchStackId", int.class);
method.invoke(options, stackId);
} catch (Exception e) {
e.printStackTrace();
}
}
return options;
}

ApplicationInfo for Settings pages in android

I'm trying to get the ApplicationInfo for Settings.ACTION_ACCESSIBILITY_SETTINGS or Settings.ACTION_BATTERY_SAVER_SETTINGS, so that I can launch them directly.
I tried following steps but it's return setting's ApplicationInfo.
private static final String[] SETTINGS_ACTION_MENUS = new String[]{
Settings.ACTION_ACCESSIBILITY_SETTINGS,Settings.ACTION_ADD_ACCOUNT};
public void getSettingPages(){
for(String menu : SETTINGS_ACTION_MENUS){
final Intent intent = new Intent(menu);
ComponentName componentName = intent.resolveActivity(packageManager);
if(componentName != null){
try {
ApplicationInfo info = packageManager.getApplicationInfo(componentName.getPackageName(),0);
if(packageManager.getLaunchIntentForPackage(info.packageName) != null){
launchableApps.add(info);
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
}
}
I tried following steps but it's return setting's ApplicationInfo
That is because those Intent actions are tied to activities in the Settings app. Individual activities do not have their own ApplicationInfo.

How to check MIUI autostart permission programmatically?

I need to check programmatically if the auto start permission for my app in MIUI phone is on or off. Facebook and whatsapp have this permission already enabled by default , how can I do so?
For now it's not possible.
As it's completely depend on their operating system API's and customisation. Even developers have requested for this on XIOMI's official forums but there is no response from there side.
Till now even i am finding an answer to this question but nothing helped me.
For the time being it will be only possible for rooted phones. i.e. making customisation in their firmware by becoming super user. But this is not at all advisable as it may damage user's phone.
EDIT 1
You can redirect user to autostart permission's settings page for enabling your app using following code
String manufacturer = "xiaomi";
if (manufacturer.equalsIgnoreCase(android.os.Build.MANUFACTURER)) {
//this will open auto start screen where user can enable permission for your app
Intent intent1 = new Intent();
intent1.setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity"));
startActivity(intent1);
}
EDIT 2
I have recently used Mi A1 from XIOMI which have stock android (not miui) so this phone does not have autostart permission settings from miui. So take care while navigating user to the settings in such devices because it will not work here.
100% working for oppo, vivo, xiomi, letv huawei, and honor
just call this function
private void addAutoStartup() {
try {
Intent intent = new Intent();
String manufacturer = android.os.Build.MANUFACTURER;
if ("xiaomi".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity"));
} else if ("oppo".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity"));
} else if ("vivo".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity"));
} else if ("Letv".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity"));
} else if ("Honor".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity"));
}
List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (list.size() > 0) {
startActivity(intent);
}
} catch (Exception e) {
Log.e("exc" , String.valueOf(e));
}
}
This is not a perfect solution by any means and it requires some testing, but I've been able to detect the autostart permission on my Xiaomi device with it.
The autostart permission allows apps to be started by receiving an implicit broadcast intent. This method consists of scheduling an implicit broadcast with AlarmManager, killing the app and checking if the broadcast caused it to respawn. A second explicit intent is also scheduled just to make sure that the app is started eventually.
public class AutostartDetector extends BroadcastReceiver {
// I've omitted all the constant declaration to keep this snippet concise
// they should match the values used in the Manifest
public static void testAutoStart(Context context) {
long now = System.currentTimeMillis();
// this ID is for matching the implicit and explicit intents
// it might be unnecessary
String testId = Long.toHexString(now);
Intent implicitIntent = new Intent(ACTION_IMPLICIT_BROADCAST);
// the category is set just to make sure that no other receivers handle the broadcast
implicitIntent.addCategory(CATEGORY_AUTOSTART);
implicitIntent.putExtra(EXTRA_TEST_ID, testId);
PendingIntent implicitPendingIntent =
PendingIntent.getBroadcast(context, REQUEST_CODE_IMPLICIT_BROADCAST, implicitIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent explicitIntent = new Intent(ACTION_EXPLICIT_BROADCAST);
explicitIntent.addCategory(CATEGORY_AUTOSTART);
explicitIntent.setComponent(new ComponentName(context, AutostartDetector.class));
explicitIntent.putExtra(EXTRA_TEST_ID, testId);
PendingIntent explicitPendingIntent =
PendingIntent.getBroadcast(context, REQUEST_CODE_EXPLICIT_BROADCAST, explicitIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// calling commit() makes sure that the data is written before we kill the app
// again, this might be unnecessary
getSharedPreferences(context).edit().putInt(testId, TestStatus.STARTED).commit();
// the explicit intent is set with an additional delay to let the implicit one be received first; might require some fine tuning
alarmManager.set(AlarmManager.RTC_WAKEUP, now + BASE_DELAY, implicitPendingIntent);
alarmManager.set(AlarmManager.RTC_WAKEUP, now + BASE_DELAY + EXPLICIT_INTENT_DELAY, explicitPendingIntent);
// kill the app - actually kind of tricky, see below
SelfKiller.killSelf(context);
}
#Override
public void onReceive(Context context, Intent intent) {
SharedPreferences sharedPreferences = getSharedPreferences(context);
String testId = intent.getStringExtra(EXTRA_TEST_ID);
if (testId == null) {
Log.w(TAG, "Null test ID");
return;
}
if (!sharedPreferences.contains(testId)) {
Log.w(TAG, "Unknown test ID: " + testId);
return;
}
String action = intent.getAction();
if (ACTION_IMPLICIT_BROADCAST.equals(action)) {
// we could assume right here that the autostart permission has been granted,
// but we should receive the explicit intent anyway, so let's use it
// as a test sanity check
Log.v(TAG, "Received implicit broadcast");
sharedPreferences.edit().putInt(testId, TestStatus.IMPLICIT_INTENT_RECEIVED).apply();
} else if (ACTION_EXPLICIT_BROADCAST.equals(action)) {
Log.v(TAG, "Received explicit broadcast");
int testStatus = sharedPreferences.getInt(testId, -1);
switch (testStatus) {
case TestStatus.STARTED:
// the implicit broadcast has NOT been received - autostart permission denied
Log.d(TAG, "Autostart disabled");
sharedPreferences.edit().putBoolean(PREF_AUTOSTART_ENABLED, false).apply();
notifyListener(false);
break;
case TestStatus.IMPLICIT_INTENT_RECEIVED:
// the implicit broadcast has been received - autostart permission granted
Log.d(TAG, "Autostart enabled");
sharedPreferences.edit().putBoolean(PREF_AUTOSTART_ENABLED, true).apply();
notifyListener(true);
break;
default:
Log.w(TAG, "Invalid test status: " + testId + ' ' + testStatus);
break;
}
}
}
private interface TestStatus {
int STARTED = 1;
int IMPLICIT_INTENT_RECEIVED = 2;
}
Receiver declaration in the manifest:
<receiver android:name=".autostart.AutostartDetector">
<intent-filter>
<category android:name="com.example.autostart.CATEGORY_AUTOSTART"/>
<action android:name="com.example.autostart.ACTION_IMPLICIT_BROADCAST"/>
<action android:name="com.example.autostart.ACTION_EXPLICIT_BROADCAST"/>
</intent-filter>
</receiver>
Killing the app reliably is another problem. I've been using this helper method:
public static void killSelf(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
activityManager.killBackgroundProcesses(context.getPackageName());
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
// this is all we can do before ICS. luckily Xiaomi phones have newer system versions :)
System.exit(1);
return;
}
// set up a callback so System.exit() is called as soon as all
// the activities are finished
context.registerComponentCallbacks(new ComponentCallbacks2() {
#Override
public void onTrimMemory(int i) {
if (i == TRIM_MEMORY_UI_HIDDEN) {
Log.v(TAG, "UI Hidden");
System.exit(1);
}
}
/* ... */
});
// see below
ActivityTracker.getInstance().finishAllActivities();
}
ActivityTracker is another utility that keeps track of activity lifecycles. Make sure to register it in the Application subclass.
#RequiresApi(api = Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public final class ActivityTracker implements Application.ActivityLifecycleCallbacks {
private final ArraySet<Activity> mCreatedActivities = new ArraySet<>();
public static ActivityTracker getInstance() {
return Holder.INSTANCE;
}
public static void init(Application application) {
application.registerActivityLifecycleCallbacks(getInstance());
}
public static void release(Application application) {
ActivityTracker activityTracker = getInstance();
application.unregisterActivityLifecycleCallbacks(activityTracker);
activityTracker.mCreatedActivities.clear();
}
public void finishAllActivities() {
// iterate over active activities and finish them all
for (Activity activity : mCreatedActivities) {
Log.v(TAG, "Finishing " + activity);
activity.finish();
}
}
public Set<Activity> getCreatedActivities() {
return Collections.unmodifiableSet(mCreatedActivities);
}
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
mCreatedActivities.add(activity);
}
#Override
public void onActivityDestroyed(Activity activity) {
mCreatedActivities.remove(activity);
}
private static final class Holder {
private static final ActivityTracker INSTANCE = new ActivityTracker();
}
/* ... */
}
You might also want to stop all the services just to be sure.
In addition to Nikhil's answer:
First of all, some apps like Facebook, Whatsapp are whitelisted from Xiomi by default that means auto start permission will automatically be on for these apps.
I also didn't find any way to check for auto start permission if it's enabled or not and enable it programmatically. Though as above answer suggests we can redirect user to auto start permission activity but when we have to redirect user we still don't know and also this will not work in all of the Xiomi devices.
So I used an alternative for my sync adapter to work. I stored a boolean variable named "isSyncAdapterRunning" in shared preferences and set the value of it every time sync adapter runs. This way I'll be able to know if my sync adapter is working or not.
//in my sync adapter
#Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
Log.e("TAG", "SyncStarted");
performSync(true);
}
public static void performSync(boolean fromSyncAdapterClass){
//write your code for sync operation
if(fromSyncAdapterClass){
setValueOfIsSyncAdapterRunningVariable();
}
}
I made other background service to perform same task if sync adapter is not working.
//In my other background service
public class BackgroundSyncService extends IntentService {
public BackgroundSyncService() {
super("BackgroundSyncService");
}
#Override
protected void onHandleIntent(Intent intent) {
SyncAdapter.performSync(false);
}
}
Now start sync adapter:
// start your sync adapter here
//And after that just start that service with a condition
if(!getValueOfIsSyncAdapterRunningVariable()){
startService(new Intent(context, BackgroundSyncService.class));
}
So basically I'm running another service to perform same task in background if my sync adapter is not working and the best thing is only one of them will run at a time.
Above code will fail if user turn on auto start permission and turn off again because value of boolean variable is already set. For that you can set value of boolean variable to default once in every 24Hrs.
Hope this helps.
For now it's not possible.
As it's completely depend on their operating system API's and customization. But i implemented a fix using SharedPreference. It doesn't solved the problem but it prevents app from opening setting screen everytime app is opened. Example :
if (AppPref.getAutoStart(context).isEmpty() && AppPref.getAutoStart(context).equals("")) {
enableAutoStart();
}
private void enableAutoStart() {
if (Build.BRAND.equalsIgnoreCase("xiaomi")) {
new AlertDialog.Builder(context)
.setTitle("Enable AutoStart")
.setMessage("Please allow this app to always run in the background,else our services can't be accessed.")
.setNegativeButton("Deny", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
AppPref.setAutoStart(context, "");
dialog.dismiss();
}
})
.setPositiveButton("ALLOW", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
try {
AppPref.setAutoStart(context, "1");
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.miui.securitycenter",
"com.miui.permcenter.autostart.AutoStartManagementActivity"));
startActivity(intent);
} catch (Exception e) {
Toast.makeText(context, "Can't perform action", Toast.LENGTH_SHORT).show();
}
dialog.dismiss();
}
})
.create()
.show();
}
}
This code worked for me. Simple and easy . Credit
private State getAutoStartState(Activity activity) throws Exception {
Class<?> clazz;
try {
clazz = Class.forName(CLAZZ);
} catch (ClassNotFoundException ignored) {
// we don't know if its enabled, class
// is not found, no info
return State.NO_INFO;
}
final Method method = getMethod(clazz);
if (method == null) {
// exception raised while search the method,
// or it doesn't exist
return State.NO_INFO;
}
// the method is a public method, It's still
// better to do this
method.setAccessible(true);
// the target object is null, because the
// method is static
final Object result = method.invoke(null, getActivity(),
getActivity().getPackageName());
// the result should be an Int
if (!(result instanceof Integer))
throw new Exception();
final int _int = (int) result;
if (_int == ENABLED)
return State.ENABLED;
else if (_int == DISABLED)
return State.DISABLED;
return State.UNKNOWN;
}
private Method getMethod(Class<?> clazz) {
try {
return clazz.getDeclaredMethod("getApplicationAutoStart",
Context.class, String.class);
} catch (Exception ignored) {
// this should not happen, probably
// MIUI version is updated, lets give a last try
return null;
}
}
public void checkMIUIAutoStart(Activity activity) throws Exception {
if (getAutoStartState(activity) == State.DISABLED) {
String manufacturer = "xiaomi";
if (manufacturer.equalsIgnoreCase(android.os.Build.MANUFACTURER)) {
//this will open auto start screen where user can enable permission for your app
Intent intent1 = new Intent();
intent1.setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity"));
startActivity(intent1);
}
}else {
Toast.makeText(activity, "Auto-start is enabled.", Toast.LENGTH_SHORT).show();
}
}
You cannot check whether autorun permission is enabled or not because autorun feature is provided by customised os only not by android os like mi, vivo, oppo, letv etc
This is a workaround tested on MI, Honor and vivo phones.
To check whether os is customised like miui, honor ui copy and paste this method in activity, fragment or util class
public static void getAutoStartPermission(final Activity context) {
final String build_info = Build.BRAND.toLowerCase();
switch (build_info) {
case "xiaomi":
Utilities.Companion.showAutorunDialog(context);
break;
case "letv":
Utilities.Companion.showAutorunDialog(context);
break;
case "oppo":
Utilities.Companion.showAutorunDialog(context);
break;
case "vivo":
Utilities.Companion.showAutorunDialog(context);
break;
case "Honor":
Utilities.Companion.showAutorunDialog(context);
break;
default:
break;
}
}
Where
fun showAutorunDialog(context: Context) {
val builder = AlertDialog.Builder(context)
//set title for alert dialog
builder.setTitle("Alert")
//set message for alert dialog
builder.setMessage("Enable Autostart permission for this app if its disabled in app settings in order to run application in background.")
builder.setCancelable(true)
//performing positive action
builder.setPositiveButton("Enable") { _, _ ->
addAutoStartup(context)
}
// Create the AlertDialog
var vpnDialog = builder.create()
// Set other dialog properties
vpnDialog!!.setCancelable(false)
vpnDialog!!.show()
}
private fun addAutoStartup(context:Context) {
try {
val intent = Intent()
val manufacturer = Build.MANUFACTURER
if ("xiaomi".equals(manufacturer, ignoreCase = true)) {
intent.component = ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity")
} else if ("oppo".equals(manufacturer, ignoreCase = true)) {
intent.component = ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity")
} else if ("vivo".equals(manufacturer, ignoreCase = true)) {
intent.component = ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity")
} else if ("Letv".equals(manufacturer, ignoreCase = true)) {
intent.component = ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity")
} else if ("Honor".equals(manufacturer, ignoreCase = true)) {
intent.component = ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity")
}
val list: List<ResolveInfo> = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
if (list.size > 0) {
context.startActivity(intent)
}
} catch (e: java.lang.Exception) {
Log.e("exc", e.toString())
}
}
You could use this library to check the autostart permission state on MIUI 10, 11 and 12.
https://github.com/XomaDev/MIUI-autostart
// make sure device is MIUI device, else an
// exception will be thrown at initialization
Autostart autostart = new Autostart(applicationContext);
State state = autostart.getAutoStartState();
if (state == State.DISABLED) {
// now we are sure that autostart is disabled
// ask user to enable it manually in the settings app
} else if (state == State.ENABLED) {
// now we are also sure that autostart is enabled
}
To check if permission enabled, I just starting a foreground service and check if is running.
Service:
class ExtraPermissionStateService: Service() {
companion object {
private var instance: ExtraPermissionStateService? = null
fun isAppCanRunOnBackground(context: Context): Boolean {
val serviceIntent = Intent(context, ExtraPermissionStateService::class.java)
context.startService(serviceIntent)
return instance != null
}
}
override fun onBind(p0: Intent?): IBinder? {
return null
}
override fun onCreate() {
super.onCreate()
instance = this
}
override fun onDestroy() {
super.onDestroy()
instance = null
}
}
call it:
ExtraPermissionStateService.isAppCanRunOnBackground(context)
And don't forget on the manifest:
<service android:name=".helpers.utils.ExtraPermissionStateService"/>
I have tried the below solution and it worked for me. If the "Auto Start" is enabled it will return "true", if not it will return "false".
public class CustomPermissionCheck {
private static final String TAG = "CustomPermissionCheck";
private Context context;
private static final int APP_AUTO_START_PERMISSION_CODE = 10008;
public CustomPermissionCheck(Context context) {
this.context = context;
}
public boolean isAutoStartEnabled() {
try {
AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
Method method = AppOpsManager.class.getMethod("checkOpNoThrow", int.class, int.class, String.class);
int result = (int) method.invoke(appOpsManager, APP_AUTO_START_PERMISSION_CODE, android.os.Process.myUid(), context.getPackageName());
boolean isEnabled = result == AppOpsManager.MODE_ALLOWED;
return isEnabled;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
You have to do allow and deny for system permissions.
below is the code:
private boolean checkPermission(){
int result = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Snackbar.make(view,"Permission Granted, Now you can access location data.",Snackbar.LENGTH_LONG).show();
} else {
Snackbar.make(view,"Permission Denied, You cannot access location data.",Snackbar.LENGTH_LONG).show();
}
break;
}
}

How to check if Facebook is installed Android

I am modifying my app to be able to catch if a user tries to publish without having the facebook app installed (required for SSO). Here is the code I am using:
try{
ApplicationInfo info = getPackageManager().
getApplicationInfo("com.facebook.android", 0 );
return true;
} catch( PackageManager.NameNotFoundException e ){
return false;
}
The problem is, it is always catching an error. According to the question here, I need to request the appropriate permission but I don't know what permissions I need to request.
Is my problem a permission one or something else?
com.facebook.android is the package name for the Facebook SDK. The Facebook app's package is com.facebook.katana.
To check whether or not an app is installed on Android use this method:
public static boolean isPackageInstalled(Context c, String targetPackage) {
PackageManager pm = c.getPackageManager();
try {
PackageInfo info = pm.getPackageInfo(targetPackage, PackageManager.GET_META_DATA);
} catch (NameNotFoundException e) {
return false;
}
return true;
}
In your case use any of these packages:
com.facebook.orca
com.facebook.katana
com.example.facebook
com.facebook.android
boolean hasPackage = isPackageInstalled(MainActivity.this, "com.facebook.katana");
For Kotlin
fun isPackageInstalled(packageName: String, context: Context): Boolean {
return try {
val packageManager = context.packageManager
packageManager.getPackageInfo(packageName, 0)
true
} catch (e: PackageManager.NameNotFoundException) {
false
}
}
if (isAppInstalled()) {
Toast.makeText(getApplicationContext(), "facebook app already installed", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "facebook app not installing", Toast.LENGTH_SHORT).show();
}
public boolean isAppInstalled() {
try {
getApplicationContext().getPackageManager().getApplicationInfo("com.facebook.katana", 0);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
Write the function in Utilities or anywhere suit for you.This will function will help you to check any app installed or not.let me say for myself it is in Utilities.java
public static boolean isAppInstalled(Context context, String packageName) {
try {
context.getPackageManager().getApplicationInfo(packageName, 0);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
Then, Call this function from anywhere. for eg to check facebook app
if(Utilities.isAppInstalled(getApplicationContext(), "com.facebook.katana")) {
// Do something
}else {
Intent i = new Intent(android.content.Intent.ACTION_VIEW);
i.setData(Uri.parse("https://play.google.com/store/apps/details?id=com.facebook.katana"));
startActivity(i);
}
Enjoy
You can check it for all Facebook Apps that any of Facebook apps are installed or not .
For supporting OS level 11 we need to add this in AndrodiManifest.xml to avoid package name not found exception -
<manifest ...
<queries>
<package android:name="com.facebook.katana" />
<package android:name="com.facebook.lite" />
<package android:name="com.facebook.android" />
<package android:name="com.example.facebook" />
</queries>
<application .....
Then add this method to you code -
public static String isFacebookAppInstalled(Context context){
if(context!=null) {
PackageManager pm=context.getPackageManager();
ApplicationInfo applicationInfo;
//First check that if the main app of facebook is installed or not
try {
applicationInfo = pm.getApplicationInfo("com.facebook.katana", 0);
return applicationInfo.enabled?"com.facebook.katana":"";
} catch (Exception ignored) {
}
//Then check that if the facebook lite is installed or not
try {
applicationInfo = pm.getApplicationInfo("com.facebook.lite", 0);
return applicationInfo.enabled?"com.facebook.lite":"";
} catch (Exception ignored) {
}
//Then check the other facebook app using different package name is installed or not
try {
applicationInfo = pm.getApplicationInfo("com.facebook.android", 0);
return applicationInfo.enabled?"com.facebook.android":"";
} catch (Exception ignored) {
}
try {
applicationInfo = pm.getApplicationInfo("com.example.facebook", 0);
return applicationInfo.enabled?"com.example.facebook":"";
} catch (Exception ignored) {
}
}
return "";
}
And then launch the app -
if (!TextUtils.isEmpty(isFacebookAppInstalled(context))) {
/* Facebook App is installed,So launch it.
It will return you installed facebook app's package
name which will be useful to launch the app */
Uri uri = Uri.parse("fb://facewebmodal/f?href=" + yourURL);
Intent intent = context.getPackageManager().getLaunchIntentForPackage(isFacebookAppInstalled(context);
if (intent != null) {
intent.setAction(Intent.ACTION_VIEW);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
else {
Intent intentForOtherApp = new Intent(Intent.ACTION_VIEW, uri);
context.startActivity(intentForOtherApp);
}
}
Best Approach is to pick the package name including com.facebook but anyway you may use following packages:
com.facebook.orca
com.facebook.katana
com.example.facebook
com.facebook.android
Intent i = new Intent(android.content.Intent.ACTION_VIEW);
i.setData(Uri.parse("https://play.google.com/store/apps/details?id=com.facebook.katana"));
startActivity(i);
this code worked for me
if (isAppInstalled()) {
Toast.makeText(getApplicationContext(), "facebook app already installed", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "facebook app not installing", Toast.LENGTH_SHORT).show();
}
public boolean isAppInstalled() {
try {
getApplicationContext().getPackageManager().getApplicationInfo("com.facebook.katana", 0);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
myWebView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.e("tag","url override url = "+ url);
if( url.startsWith("http:") || url.startsWith("https:") ) {
return false;
}
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity( intent );
return true;
}
});

Categories

Resources