In my project I can get the list of all installed application by the following code:
public class ApplicationFilterActivity extends Activity implements
OnItemClickListener {
ListView appfilter;
SharedPreferences preferences;
public static String filenames = "RotateData";
PackageManager pck;
ArrayList<Applications> results = new ArrayList<Applications>();
ArrayList<String> gotPackagename = new ArrayList<String>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
appfilter = (ListView) findViewById(R.id.lvApp);
preferences = getSharedPreferences(filenames, 0);
PackageManager packageManager = this.getPackageManager();
List<PackageInfo> applist = packageManager.getInstalledPackages(0);
Iterator<PackageInfo> it = applist.iterator();
while (it.hasNext()) {
PackageInfo pk = (PackageInfo) it.next();
results.add(new Applications(pk.applicationInfo
.loadIcon(packageManager), ""
+ pk.applicationInfo.loadLabel(packageManager)));
Log.i("AppName", "" + pk.applicationInfo.packageName);
gotPackagename.add(pk.applicationInfo.packageName);
}
appfilter.setAdapter(new Customarrayadapter(this, results));
appfilter.setOnItemClickListener(this);
}
}
but now I want to filter that the list will show only the games , is it possible?
There is no way to set your app as "Game Type" in Android, so you could not filter apps by category.
I think, best solution - to parse all games packages (game name could be different because of phone localization) from Google Play and put that list in app and sometimes update it from your server. If you always got internet connection in your application you could send found apps list to server and server will return back games from that list. So, you need to write server code for that.
You could get the package name of every app installed on the device and scrape the google play store to see if that app is in one of the games categories. But that's a bit hackish :).
So first add this permission in your Manifest file
uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
it will return a boolean if it's true then your package name is from game category
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
binding = GameListBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
final PackageManager pm = getPackageManager();
//get a list of installed apps.
List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo packageInfo : packages) {
Boolean b = checkAppIsGame(GameList.this,packageInfo.packageName);
if(b){
Toast.makeText(GameList.this, "This is Game "+ packageInfo.packageName, Toast.LENGTH_SHORT).show();
}
}
}
public static boolean checkAppIsGame(Context context, String packageName) {
try {
ApplicationInfo info = context.getPackageManager().getApplicationInfo(packageName, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Log.e("MyGame", "App Packagename is game : " + packageName);
return info.category == ApplicationInfo.CATEGORY_GAME;
} else {
Toast.makeText(context, "is game 2 " + packageName, Toast.LENGTH_SHORT).show();
Log.e("Util", "Package is game 2 : " + packageName);
return (info.flags & ApplicationInfo.FLAG_IS_GAME) == ApplicationInfo.FLAG_IS_GAME;
}
} catch (PackageManager.NameNotFoundException e) {
Log.e("MyGame", "Package info Not Found For : " + packageName, e);
return false;
}
}
No it is not possible.
Catagories are only for using in market Applications don't have any identifier to distinguish between app catagories.
Related
I am making an android app that asks for the users to select a Bluetooth paired device via spinner.
When the user opens the app first time, user selects a Bluetooth paired device** from list. Then when app opens second time, I want the same Bluetooth paired device to be selected. I don't want user to select the paired device every time the app is opened. How to do that?
Spinner btPairedDevicesSpinner;
BluetoothManager mBluetoothManager;
BluetoothAdapter mBluetoothAdapter;
BluetoothDevice [] mBluetoothDeviceArray;
btPairedDevicesSpinner = findViewById(R.id.btPairedDevicesSpinner);
mGetBluetoothPairedDevice ();
btPairedDevicesSpinner.setOnItemSelectedListener(mPairedDeviceOnItemSelectedListener);
public void mGetBluetoothPairedDevice () {
Set<BluetoothDevice> mPairedDevice = mBluetoothAdapter.getBondedDevices();
mBluetoothDeviceArray = new BluetoothDevice[mPairedDevice.size()];
String [] strings = new String[mPairedDevice.size()];
int index = 0;
if (mPairedDevice.size() > 0) {
for (BluetoothDevice device : mPairedDevice) {
mBluetoothDeviceArray [index] = device;
strings [index] = device.getName();
index++;
}
}
else {
String mOnDevice = "No Device found";
mPairedDeviceArrayAdapter.add(mOnDevice);
}
ArrayAdapter<String> mArrayAdapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_list_item_1, strings);
btPairedDevicesSpinner.setAdapter(mArrayAdapter);
}
private final AdapterView.OnItemSelectedListener mPairedDeviceOnItemSelectedListener = new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
ConnectThread mConnectThread = new ConnectThread(mBluetoothDeviceArray [i], view);
mConnectThread.start();
mBluetoothToolBar.setSubtitle("Connecting");
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
Toast.makeText(BluetoothMain.this, "Nothing is selected", Toast.LENGTH_SHORT).show();
}
};
One way that should work. Store the selected device name in shared preferences. (Create the sharedPref object somewhere else like onCreate() and do the edit in spinners onItemChanged() )
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
sharedPref.edit().putString("btDeviceName", "the name").apply();
After calling
btPairedDevicesSpinner.setAdapter(mArrayAdapter);
load the device name from shared preferences and if there is one call setSelection() on spinner
String deviceName = sharedPref.getString("btDeviceName", null);
if(deviceName != null){
btPairedDevicesSpinner.setSelection(mArrayAdapter.getPosition("deviceName "));
}
I'm making an app where it uses intent to send data to another app. In case, the other app, which is supposed to receive data from my app, is not installed on users's device then it redirects user to play store with toast message asking user to install it. I used "if else" to achieve this. It worked all good until I found that if the other app is disabled by user (OEM installed app which can't be uninstalled), then my app crashes. In such a condition, I want to let user know that the app is disabled by them and ask them to enable it (through toast message). How can I achieve this?
Here is my complete code:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Creates button view which is connected to a view in the XML layout, which gets triggered on touching the view.
TextView textView = (TextView) findViewById(R.id.location);
textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Use package name which we want to check
boolean isAppInstalled = appInstalledOrNot("com.google.android.apps.maps");
if(isAppInstalled){
Uri gmmIntentUri = Uri.parse("geo:00,0000,00,0000");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
mapIntent.setPackage("com.google.android.apps.maps");
startActivity(mapIntent);
} else {
Uri uri2 = Uri.parse("market://details?id=com.google.android.apps.maps");
Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri2);
Toast.makeText(MainActivity.this, "Google Maps not Installed", Toast.LENGTH_SHORT).show();
startActivity(goToMarket);
}
}
});
}
private boolean appInstalledOrNot(String uri) {
PackageManager pm = getPackageManager();
try {
pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
return true;
} catch (PackageManager.NameNotFoundException e) {
}
return false;
}
}
I'm not sure if this will work for you, but since you know the package name, you could try this to do a check beforehand.
I used this Topic
I try this code but did not work :
PACKAGE_NAME = context.getApplicationContext().getPackageName();
try {
pi = context.getPackageManager().getPackageInfo(PACKAGE_NAME, PackageManager.GET_PERMISSIONS);
for (String perm : pi.requestedPermissions) {
Log.e("Foo", perm);
}
} catch (Exception e) {
}
But it could not help me. I have the application list, I want to get the permission that used on each of them.
How can I handle it?
UPDATE:
like the photo, When clicking on "دسترسی ها", I want to get the permission that used in that app.(for example in a telegram: Internet, storage, call, camera,...)
UPDATE 2:
I will share the adapter code for my problem
My Adapter:
class AppViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
AppViewHolder(View itemView, Context context, List<App> apps) {
super(itemView);
txt_show_permission = itemView.findViewById(R.id.txt_show_permission);
/*The String Buffer For Permissions*/
appNameAndPermissions = new StringBuffer();
PackageManager pm = context.getPackageManager();
List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo applicationInfo : packages) {
Log.d(TAG, "App: " + applicationInfo.name + " Package: " + applicationInfo.packageName);
PackageInfo packageInfo = null;
try {
packageInfo = pm.getPackageInfo(applicationInfo.packageName, PackageManager.GET_PERMISSIONS);
appNameAndPermissions.append(packageInfo.packageName + "*******:\n");
//Get Permissions
requestedPermissions = packageInfo.requestedPermissions;
if (requestedPermissions != null) {
for (int i = 0; i < requestedPermissions.length; i++) {
Log.d(TAG, requestedPermissions[i]);
appNameAndPermissions.append(requestedPermissions[i] + "\n");
}
appNameAndPermissions.append("\n");
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
}
set On Click Listener On txt_show_permission in onBindViewHolder:
holder.txt_show_permission.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showDialog(String.valueOf(appNameAndPermissions));
}
});
Method for dialog in adapter class:
public void showDialog(String txtPermission) {
final Dialog dialog = new Dialog(context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCancelable(false);
dialog.setContentView(R.layout.show_permission_dialog);
TextView txt_permission = dialog.findViewById(R.id.txt_permission);
Button btn_ok = dialog.findViewById(R.id.btn_ok);
txt_permission.setText(txtPermission);
btn_ok.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
}
You can loop through all the app names and get their permissions and store them in a String Buffer like this:
https://stackoverflow.com/a/14672557/10058326
Or since you want permissions to be shown on button click, you can add for each app the code you have tried with the proper app name in a OnButtonClickListener
Or you can extract the relevant permissions from the StringBuffer made earlier each time the button is clicked
EDIT: See these links on how to create a OnItemClickListener for the Recycler View. You can get the position of the row that was clicked and through that get the app name in that row which you can pass to another function. Then write code inside that function to get permissions for the app name passed and display it
https://antonioleiva.com/recyclerview-listener/
https://hackernoon.com/android-recyclerview-onitemclicklistener-getadapterposition-a-better-way-3c789baab4db
https://gist.github.com/riyazMuhammad/1c7b1f9fa3065aa5a46f
EDIT 2:
Instead of passing appNameAndPermissions to showDialog which contains the whole list, you need to extract permissions of a certain app from the String Buffer. Here's how:
String app_name = itemView.findViewById(R.id.app_name_text_view).getText().toString();
int indexOfApp = appNameAndPermissions.indexOf(app_name);
int indexOfLastPermission = appNameAndPermissions.indexOf("\n", indexOfApp);
String permissions = appNameAndPermissions.substring(indexOfApp, indexOfLastPermission);
I have had a device, which apparently had something broken with the orientation, because after reboot, for about an hour, it would rotate the screen in response to a change of orientation - and then it would stop responding, both on the "desktop" level and application level.
So, I found Change Screen Orientation programmatically using a Button, and I assumed I can create a "icon button only" app, which when pressed, would not run a new application, but instead just try to change the orientation.
The skeleton for the "icon/button-only" app is a copy of Lock screen (it.reyboz.screenlock). I posted this project on a gist - but since it is hard to have folders (and binary files) by default in a gist, this is the procedure you can use to get the code:
git clone https://gist.github.com/e6422677cababc17526d0cb57aceb76a.git dl_archive_git
cd dl_archive_git
bash run-me-to-unpack.sh
# check upacked dir:
tree rotate-btn-droid
cd rotate-btn-droid/
# change your SDK path (ASDKPATH) in buildme.sh, and then:
bash buildme.sh
# if your java install is not in the path, then call the last command with JAVA_HOME prepended:
# JAVA_HOME=/path/to/jdkXXX bash buildme.sh
Basically, I'm just trying to do the following in MainActivity.java:
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
int orientation = display.getOrientation();
// OR: orientation = getRequestedOrientation(); // inside an Activity
switch(orientation) {
case Configuration.ORIENTATION_PORTRAIT:
setRequestedOrientation (Build.VERSION.SDK_INT < 9 ?
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE :
ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
break;
case Configuration.ORIENTATION_LANDSCAPE:
setRequestedOrientation (Build.VERSION.SDK_INT < 9 ?
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT :
ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
break;
}
... however, nothing happens when I click the app icon and run this code.
So, my question is - is it possible in principle to force a change of the device orientation on a "desktop" level? If so, is it dependent on Android version (possibly vendor branded) or not - and how?
Was just curious so tried out Sam's solution and made some changes :
Would need this permission in Manifest
Permission <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Also this permissions is a dangerous permission but if you are installing the app from Play store you need not worry about that.
I made a window service something like this :
public class MyServiceNew extends Service {
private View view;
public MyServiceNew() {
}
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
int flag = intent.getExtras().getInt("Flag");
WindowManager.LayoutParams layout;
if (flag == 1) {
layout = generateLayoutLandscape();
} else {
layout = generateLayoutPortrait();
}
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(view, layout);
return super.onStartCommand(intent, flags, startId);
}
private WindowManager.LayoutParams generateLayoutPortrait() {
Toast.makeText(this, "Port", Toast.LENGTH_LONG).show();
view = new View(this);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSPARENT);
params.alpha = 0f;
params.width = 0;
params.height = 0;
//The orientation to force
params.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
return params;
}
private WindowManager.LayoutParams generateLayoutLandscape() {
Toast.makeText(this, "Land", Toast.LENGTH_LONG).show();
view = new View(this);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSPARENT);
params.alpha = 0f;
params.width = 0;
params.height = 0;
//The orientation to force
params.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
return params;
}
}
And from your Activity while development make sure you include ACTION_MANAGE_OVERLAY_PERMISSION ; again you don't need to worry this for users who will install the app through Google Play Store. Here using the below code to allow permission for devices above M :
public void requestSystemAlertPermission(int requestCode) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
return;
final String packageName = getPackageName();
final Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + packageName));
startActivityForResult(intent, requestCode);
}
And now just start your service and pass extras for Portrait or Landscape
I am using 1 for Landscape and 2 for Portrait
Intent intentLand = new Intent(SoNew.this, MyServiceNew.class);
intentLand.putExtra("Flag", 2); //or change 1 for Port
startService(intentLand);
Hope this helps :)
I have a android app, in which the main activity calls a function from a external library, which then opens a webview if neccesary.
Opening the webview is no problem. My problem start when people/users close the webview. It appears that the webview (I think, I am not sure though) has opened an extra activity or something on top of the original app that called the external library.
Now users have to close 2 windows, before they can continue in the original app.
Does anyone have experience with this, or knows what's happening here?
MainActivity
public class MainActivity extends Activity
{
private final String appKey = "Android.Lib.Test";
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
externalLib.Initialize(this, getIntent(), appKey);
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
External Lib
public class externalLib
{
private static final String TAG = "externalLib";
private static int messageId;
public static void Initialize(Context context, Intent intent, String newAppKey)
{
Log.d(TAG, "initializing");
APPKEY = newAppKey;
if(intent.hasExtra("url"))
{
if(intent.getExtras().getString("url") != null)
{
Intent webViewIntent = new Intent(context, externalLibWebView.class);
webViewIntent.putExtra("url", intent.getExtras().getString("url"));
context.startActivity(webViewIntent);
}
}
if(intent.hasExtra("messageId"))
{
messageId = intent.getExtras().getInt("messageId");
Log.e(TAG, "messageId: " + messageId);
}
else
{
messageId = 0;
}
}
}
I found out what the problems was. I wanted the webview to load the url, but instead, the browser was opened leaving the webview empty and thus "creating" the extra acitvity. Now the webview loads the url.