I want to get diary use for all apps installed in phone, but always an empty list is returned. Below is the code i am using.
Here app.js from react-native call apps information from native code java
loadApps = async () => {
await ReturnAppsInformations.getApps()
.then(response => {
console.log(response); // only [] <----
this.setState({ apps });
})
.catch(error => {
console.warn(error);
});
}
Here is my simple native code to return array with data
UsageStatsManager manager = (UsageStatsManager) this.reactContext.getSystemService(this.reactContext.USAGE_STATS_SERVICE);
List<UsageStats> stats =manager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,1729196, System.currentTimeMillis());
WritableArray list2 = Arguments.createArray();
for (int i = 0; i < stats.size(); i++) {
UsageStats usageStats = stats.get(i);
WritableMap appInfo2 = Arguments.createMap();
appInfo2.putString("packageName", usageStats.getPackageName());
appInfo2.putDouble("firsTimeStamp", usageStats.getFirstTimeStamp());
appInfo2.putDouble("getTotalTimeInForeground",
usageStats.getTotalTimeInForeground());
list2.pushMap(appInfo2);
}
promise.resolve(list2);
What am I doing wrong?
This is my first app so I do not have much knowledge
Updated as suggested by Julien, but still results in a empty array.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.returnappsinformations"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
</manifest>
Ok, i found those gits about it...
https://github.com/mvincent7891/UsageStatsModule
https://github.com/shimatai/react-native-android-datausage
https://github.com/lucasferreira/react-native-android-permissions
Tonight im gonna to read them... But i belive, that resolve the problem to me!! Thanks for support!!!
Have you asked and set the necessary permissions to use UsageStatsManager?
UsageStatsManager's documentation states that you need to declare android.permission.PACKAGE_USAGE_STATS in your Manifest and that it needs to be turned on in the Settings of your phone for your particular application.
EDIT:
Permission to add in your Manifest:
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
That special permission can't be granted through the normal permissions API of Android. So you'll need to redirect your users to the Settings page where they can grant it manually. You can open the right Settings screen via the Intent:
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
you need to declare android.permission.PACKAGE_USAGE_STATS in your Manifest
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
as well as check at run time
if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.PACKAGE_USAGE_STATS)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
}
for more check How to use UsageStatsManager?
As #JulienArzul pointed you need to add permission android.settings.USAGE_ACCESS_SETTINGS and then need to check whether you have it or not using below code:-
AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
int mode = appOps.checkOpNoThrow(OPSTR_GET_USAGE_STATS, myUid(), context.getPackageName());
return mode == MODE_ALLOWED;
If above condition returns false, redirect user to that permission's settings screen
Intent intent = new Intent(MainActivity.this, AppLockService.class);
intent.setAction(AppLockService.ACTION_START_FOREGROUND_SERVICE);
startService(intent);
Related
I am in situation where I need to identify incoming call phone number in Android but when using TelephonyManager.EXTRA_INCOMING_NUMBER android studio warning EXTRA_INCOMING_NUMBER is deprecated.I gone through the developers.android.com, it shows apps performing call screening should use the CallScreeningService API instead. But I can't figure out how to use CallScreeningService to get incoming call phone number. Anyone can help me?
As #Saurabh said, the new way to screen calls is through the CallScreeningService. However, for the service to work on Android Q and up, the user needs to set your app as the default caller ID & spam app (which is done by using the new RoleManager class)
Register your screening service:
<service android:name="com.example.ScreeningService"
android:permission="android.permission.BIND_SCREENING_SERVICE">
<intent-filter>
<action android:name="android.telecom.CallScreeningService"/>
</intent-filter>
</service>
Create you service class:
#RequiresApi(api = Build.VERSION_CODES.N)
class ScreeningService : CallScreeningService() {
override fun onScreenCall(details: Details) {
//code here
}
}
Request the screening role from the user in your main activity (or where ever you see as fit):
#RequiresApi(Build.VERSION_CODES.Q)
private fun requestScreeningRole(){
val roleManager = getSystemService(Context.ROLE_SERVICE) as RoleManager
val isHeld = roleManager.isRoleHeld(RoleManager.ROLE_CALL_SCREENING)
if(!isHeld){
//ask the user to set your app as the default screening app
val intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_SCREENING)
startActivityForResult(intent, 123)
} else {
//you are already the default screening app!
}
}
Catch the user's response:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
123 -> {
if (resultCode == Activity.RESULT_OK) {
//The user set you as the default screening app!
} else {
//the user didn't set you as the default screening app...
}
}
else -> {}
}
}
Apologies for using a hard coded request code >.<
Create a CallScreeningService like this:
class ScreeningService : CallScreeningService() {
override fun onScreenCall(callDetails: Call.Details) {
val phoneNumber = callDetails.handle.schemeSpecificPart
// Do stuff with phone number
}
}
And register this service in your AndroidManifest.xml:
<service android:name="your.package.ScreeningService"
android:permission="android.permission.BIND_SCREENING_SERVICE">
<intent-filter>
<action android:name="android.telecom.CallScreeningService"/>
</intent-filter>
</service>
I know it's pretty late but if someone has similar problem I found a solution that works on API 28+ for TelephonyManager. For just identifying phone number CallScreeningService is an overkill, and you could probably override users private settings or another app that blocks spam calls.
You need to add android.permission.READ_CALL_LOG in your manifest and request it in a runtime.
if (Build.VERSION.SdkInt >= BuildVersionCodes.P) {
if (ApplicationContext.CheckSelfPermission(Manifest.Permission.ReadCallLog) != Permission.Granted)
{
ActivityCompat.RequestPermissions(this, new string[] { Manifest.Permission.ReadCallLog }, ACTION_READ_CALL_LOG);
}
}
Provided user allows your app to read call log, after broad cast receiver hits OnReceive => ActionPhoneStateChanged phone number will be empty at the first instance, but second time it should be populated.
So be prepared that on Api 28+ phone number could be identified at the second time.
I am using package manager to get a list of apps for an app drawer interface in my launcher. Everything works as it should but on Android 11,the only app that shows is the Android Settings app. What changed to make this not work anymore and/or what should i do to make it work? Are app list now based on user profiles?
Here is my current list code
public static List<ApplicationInfo> getPrimaryApps(Context context) {
PackageManager pm = context.getPackageManager();
List<ApplicationInfo> res = new ArrayList<>();
ArrayList<String> hiddenPackages = new ArrayList<>();
IconPackHelper iconPackHelper = IconPackHelper.getInstance(context);
//All Apps Package Filter
Set<String> filteredPackages = new HashSet<>();
filteredPackages.add("com.android.wallpaper.livepicker");
filteredPackages.add("com.gocalsd.symphlyx");
//All Apps Blacklist
String[] flattenedPackages = SettingsProvider.get(context).getString(SettingsProvider.HIDDEN_APPS, "").split("\\|");
for (String flat : flattenedPackages) {
ComponentName cmp = ComponentName.unflattenFromString(flat);
if (cmp != null) {
hiddenPackages.add(cmp.getPackageName());
}
}
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
List<ResolveInfo> resolveInfoList = pm.queryIntentActivities(intent, 0);
//Sort all apps
Collections.sort(resolveInfoList, new ResolveInfo.DisplayNameComparator(pm));
for (ResolveInfo resolveInfo : resolveInfoList) {
ActivityInfo activityInfo = resolveInfo.activityInfo;
int iconId = IconPackHelper.getInstance(context).getResourceIdForActivityIcon(activityInfo);
if (!filteredPackages.contains(resolveInfo.activityInfo.packageName)) {
if (!hiddenPackages.contains(resolveInfo.activityInfo.packageName)) {
String appName = activityInfo.applicationInfo.loadLabel(pm).toString();
String packageName = activityInfo.packageName;
Drawable icon = null;
int extractedIconColor = 0;
//toggle themed icon
if (iconPackHelper.isIconPackLoaded() && iconPackHelper.getThemedIcon(context, packageName)) {
if (iconId != 0) {
icon = IconPackHelper.getInstance(context).getIconPackResources().getDrawable(iconId);
Bitmap iconBm = ImageUtils.drawableToBitmap(icon);
extractedIconColor = ColorProvider.getDominantColor(iconBm);
}
}
if (icon == null || !IconPackHelper.getInstance(context).isIconPackLoaded()) {
icon = activityInfo.applicationInfo.loadIcon(pm);
Bitmap iconBm = ImageUtils.drawableToBitmap(icon);
extractedIconColor = ColorProvider.getDominantColor(iconBm);
}
res.add(new ApplicationInfo(appName, icon, packageName, extractedIconColor));
}
}
}
return res;
}
In Android 11, we can see a lot of updates that improve privacy. If your app uses the PackageManager methods to get the list of installed apps in the user’s device, you will have to make some changes in your code for devices using Android 11.
Now for your users using Android 11, the code remains the same but it won’t work unless you add some additional elements in the AndroidManifest
There are 3 different ways of querying installed apps
1.Query specific packages
If you already know which apps you want to query just mention the package names inside the <queries> element in the AndroidManifest.
<manifest package="com.nd1010.app">
<queries>
<package android:name="com.fake.app" /> //replace with com.android.wallpaper.livepicker
<package android:name="com.fake.game" /> //replace with com.gocalsd.symphlyx
</queries>
...
</manifest>
2.Query using intent filter
In case you don’t know all the package names of the apps that you want to query but there is a set of apps with similar functionality that you want to query then you can use an intent filter inside the <queries> element according to your requirements like it has been done in the code snippet below.
<manifest package="com.nd1010.app">
<queries>
<intent>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="image/jpeg" />
</intent>
</queries>
...
</manifest>
The <intent> element looks like but there are few differences. <intent> element has the following restrictions:
The <intent> element can have only one <action> element.
The <data> element can only have the following attributes : mimeType, scheme and host.
3.Query all the apps
If you want to query all the apps of the user like you were doing earlier, you need to include QUERY_ALL_PACKAGES permission in the AndroidManifest. It is a normal permission and it is granted as soon as the app is installed.
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
Ideally one should request the least amount of packages and respect the user’s privacy. In most cases this permission won’t be required, only for apps like launchers it makes sense to ask the user for permission to query all the installed apps on their phone.
There is one loophole that I noticed while exploring the <queries> element if you add android.intent.action.MAIN as the action element in the intent filter, you can see almost all the apps of the user without adding the permission since almost all apps would have this element in the AndroidManifest.
I'm unable to get outgoing call number in Android Q.
I've registered receiver in the manifest with this intent filter android.intent.action.NEW_OUTGOING_CALL and in code i'm detecting outgoing phone number like this
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL"))
String nr = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
}
But i can never get the outgoing call number in Android Q, is there a workaround to get this number differently or since Android Q it is completely impossible to detect outgoing call number?
Edit: It works with previous android versions
You need to add PROCESS_OUTGOING_CALLS permission
Create OutgoingCallReceiver
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
public class OutgoingCallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
TelephonyManager tm = (TelephonyManager)context.getSystemService(Service.TELEPHONY_SERVICE);
if (tm.getCallState() == TelephonyManager.CALL_STATE_OFFHOOK) {
String number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
}
}
}
Add required permissions to read outcomming call in AndroidManifest file
<uses-permission android:name="android.permission.NEW_OUTGOING_CALL" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Request permissions at runtime
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.PROCESS_OUTGOING_CALLS, Manifest.permission.READ_PHONE_STATE},
1);
}
Add OutgoingCallReceiver in AndroidManifest file
<receiver
android:name=".application.services.OutgoingCallReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
This code will work fine with you, but when you need to upload your application on Google play, It is ok with NEW_OUTGOING_CALL and READ_PHONE_STATE permission but,
you will receive a policy notice from playStore as:
Your app manifest requests the Call Log permission group (e.g. PROCESS_OUTGOING_CALLS)
It must be actively registered as the default Phone or Assistant handler on the device.
in this case you have 2 solution only if you want to read OutCommingCall Number:
Send declaration form to google declaration form
Or Make your application dialer app
Check Developer Policy Center
From the documentation for android.intent.action.NEW_OUTGOING_CALL:
This constant was deprecated in API level 29. Apps that redirect
outgoing calls should use the CallRedirectionService API. Apps that
perform call screening should use the CallScreeningService API.
https://developer.android.com/reference/android/content/Intent
So I would implement this API first and check if it works as expected.
Answered in Kotlin, not Java:
From sdk >=29 (Android 10 and up) you can register your app as a CallRedirectionService, "to interact between Telecom and its implementor for making outgoing call with optional redirection/cancellation purposes."
This removes the need to create a custom BroadcastReceiver.
1. On your AndroidManifest.xml file:
<service
android:name=".MyCallRedirectionService"
android:exported="true"
android:permission="android.permission.BIND_CALL_REDIRECTION_SERVICE">
<intent-filter>
<action android:name="android.telecom.CallRedirectionService" />
</intent-filter>
</service>
2. Create MyCallRedirectionService:
class MyCallRedirectionService : CallRedirectionService() {
override fun onPlaceCall(
handle: Uri,
initialPhoneAccount: PhoneAccountHandle,
allowInteractiveResponse: Boolean
) {
// We can get the outgoing number from the handle parameter:
Log.i("Phone Number:", handle.toString())
}
}
3. Use the RoleManager class to prompt the user to select your app as their CallRedirectionService:
In this case, I'm requesting as soon as the app is created, over on the MainActivity onCreate() method:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (!isRedirection())
roleAcquire(RoleManager.ROLE_CALL_REDIRECTION)
}
Here are the used functions:
private fun isRedirection(): Boolean {
return isRoleHeldByApp(RoleManager.ROLE_CALL_REDIRECTION)
}
private fun isRoleHeldByApp(roleName: String): Boolean {
val roleManager: RoleManager? = getSystemService(RoleManager::class.java)
return roleManager!!.isRoleHeld(roleName)
}
private fun roleAcquire(roleName: String) {
val roleManager: RoleManager?
if (roleAvailable(roleName)) {
roleManager = getSystemService(RoleManager::class.java)
val intent = roleManager.createRequestRoleIntent(roleName)
startActivityForResult(intent, 1)
} else {
Toast.makeText(
this,
"Redirection call with role in not available",
Toast.LENGTH_SHORT
).show()
}
}
private fun roleAvailable(roleName: String): Boolean {
val roleManager: RoleManager? = getSystemService(RoleManager::class.java)
return roleManager!!.isRoleAvailable(roleName)
}
I am new to Android, now I am working on a Project which is based on GPS. I got source code from internet(traccar). my requirement is like the app should update location on each 1Km or each 1hr. but the problem is the app not working in background after some time(10 - 20 mins). Is there any solution for this ?
what should I do(in code) to exclude this app from battery optimisation when the app is launching ? is it possible ?
I think you're having 2 different problems:
1) If you want to keep your app in background you should use a foreground Service. That way your app won't be considered to be in background by the system and the chances of its process being killed are reduced drastically. The downside is that as long as your Service is in foreground you need to show a permanent notification.
2) You cannot exclude your app from battery optimization yourself, but you can prompt the user the settings to whitelist your app. In order to do that you can refer to the official docs, you'll need to add the Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS permission to the manifest and then launch an intent with action ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS. The user will then be able to whitelist your app, only she/he can do that because otherwise every app would whitelist itself and the purpose of the battery optimization would be defied.
Add this permission in your manifest file Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
Request Permission at runtime inside onCreate method of your activity...
PowerManager powerManager = (PowerManager) getApplicationContext().getSystemService(POWER_SERVICE);
String packageName = "org.traccar.client";
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Intent i = new Intent();
if (!powerManager.isIgnoringBatteryOptimizations(packageName)) {
i.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
i.setData(Uri.parse("package:" + packageName));
startActivity(i);
}
}
This is the image of the code in debug mode:
This will be the view in app:
but the application not working as it is in No Restriction mode (background activity).
I want the application to work as No Restriction mode.
Add this permission in your manifest file
Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
Request Permission at runtime inside onCreate method of your activity...
private final int MY_PERMISSIONS_IGNORE_BATTERY_OPTIMIZATIONS =1;
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS),
MY_PERMISSIONS_IGNORE_BATTERY_OPTIMIZATIONS)
// app-defined int constant. The callback method gets the
// result of the request.
}
} else {
// Permission has already been granted
}
Here is the kotlin version of #Shafeeq Mohammed Answer and it worked for me. Thank you
fun checkBatteryOptimization(mContext: Context) {
val powerManager =
mContext.getSystemService(POWER_SERVICE) as PowerManager
val packageName = mContext.packageName
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val i = Intent()
if (!powerManager.isIgnoringBatteryOptimizations(packageName)) {
i.action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
i.data = Uri.parse("package:$packageName")
mContext.startActivity(i)
}
}
}
I have defined the following permission in my the manifest of RecSched application/project:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.recschedapk"
android:versionCode="1"
android:versionName="1.0" >
<permission android:name="com.example.recschedapk.permission.DEADLY_ACT"
android:label="DeadlyActivity"
android:description="#string/permdesc"
android:permissionGroup="android.permission-group.COST_MONEY"
android:protectionLevel="dangerous" />
:
:
</manifest>
I have specified this permission in the other application(project) of WebApp:
<uses-permissiom android:name="com.example.recschedapk.permission.DEADLY_ACT" />
In the WebApp.java file I have the following function defined to check for permission at runtime:
private boolean checkPermission()
{
String permission = "com.example.recschedapk.permission.DEADLY_ACT";
int res = getBaseContext().checkCallingOrSelfPermission(permission);
Log.d("PERMCHECK", "int val : "+ res);
return (res == PackageManager.PERMISSION_GRANTED);
}
The call for the above function :
if((this.checkPermission())
return new VideoBroadCastObject(this);
The call seems to be failing no matter what. New to android here. Can anybody tell me what the problem here is??
Thanks!
if you are not currently processing an IPC, this function will always fail.
The other app does not owns/declares this permission, that leaves the only condition that the code that is executing checkPermission() must belong to a process/pid which has been granted this permission. That means checkPermission() must be executed from an IPC call. That is, an IBinder you received from the other process calls this.
I have no idea what your process flow is but you can try this...
private boolean checkPermission() {
String permission = "com.example.recschedapk.permission.DEADLY_ACT";
int res = getBaseContext().checkPermission(permission, Binder.getCallingPid(), Binder.getCallingUid());
Log.d("PERMCHECK", "int val : "+ res);
return (res == PackageManager.PERMISSION_GRANTED);
}