I am trying to use the Android function setInterruptFilter(), but the behavior is erratic. The following example code where I just do set/get produces strange results:
int filter1 = mNotificationManager.getCurrentInterruptionFilter();
mNotificationManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
int filter2 = mNotificationManager.getCurrentInterruptionFilter();
mNotificationManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE);
int filter3 = mNotificationManager.getCurrentInterruptionFilter();
mNotificationManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE);
int filter4 = mNotificationManager.getCurrentInterruptionFilter();
Also note that
INTERRUPTION_FILTER_ALL = 1;
INTERRUPTION_FILTER_NONE = 3;
INTERRUPTION_FILTER_PRIORITY = 2;
I am going through the [painful] permission process where every time I load my app through ADB, I manually go into settings and grant my app permission to access notifications. I can verify this permission in code too
if (!mNotificationManager.isNotificationPolicyAccessGranted()) {...}
I only get the correct output when I begin in a state where INTERRUPTION_FILTER_ALL (==1). What could be going on here?
Because of a bug in Oxygen O.S. that was resolved in version 3.2.2
Related
I am working on a personal project and I am using flutter to develop an app (cross platform) that reads in the user's health data from google fit (Android) or Apple Health. I am using this package and even the EXACT same code like in the documentation (I am currently only testing on Android):
Future fetchStepData() async {
int? steps;
// get steps for today (i.e., since midnight)
final now = DateTime.now();
final midnight = DateTime(now.year, now.month, now.day);
bool requested = await health.requestAuthorization([HealthDataType.STEPS]);
if (requested) {
try {
steps = await health.getTotalStepsInInterval(midnight, now);
} catch (error) {
print("Caught exception in getTotalStepsInInterval: $error");
}
print('Total number of steps: $steps');
setState(() {
_nofSteps = (steps == null) ? 0 : steps;
_state = (steps == null) ? AppState.NO_DATA : AppState.STEPS_READY;
});
} else {
print("Authorization not granted - error in authorization");
setState(() => _state = AppState.DATA_NOT_FETCHED);
}
}
Then I am calling this function with await and I also have inserted the correct permission in all Android Manifest files:
Also I set up an OAuth2 Client ID for the project and added my google account as a test user.
BUT THE FUNCTION SETS THE VARIABLE STEPS ALWAYS TO NULL? The boolean variable "requested" is true, so it seems like the actual connection is working?
I am really disappointed by myself guys and I really need help - THANK YOU!
I tried adding the correct android permissions, asking for permissions explicitly, different time intervalls but nothing worked for me, I always got a null value back.
I have some Android code in Kotlin that is getting the status of a stored SMS message:
val status = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Sms.STATUS))
Later on, I compare this value to the different constants to see what the status means:
print(when (status) {
Telephony.Sms.STATUS_COMPLETE -> "complete"
Telephony.Sms.STATUS_FAILED -> "failed"
Telephony.Sms.STATUS_NONE -> "none"
Telephony.Sms.STATUS_PENDING -> "pending"
else -> status.toString()
})
Usually, I get strings like "complete", "none" and "pending". However, sometimes "70" is returned, which means that the status doesn't match any of the constants found listed here. What does 70 mean here?
After digging in the source code (specifically class SmsMessage, field status) I found out this document. When you scroll to section 9.2.3.15, page 68, you will see list of possible status codes for SMS. Your code (70) means
1000110 SM Validity Period Expired
In some cases, this error code is returned when the carrier determines that it is impossible to route the SMS and the message has to be dropped as it is being looped between platforms.
Error code : 70
Destination permanently unavailable The destination (i.e., “dst”)
phone number is not active and there is no indication of when it will become available again. Note that this is a broad error code where the carrier has not indicated the reason for the destination unavailability. Check the “dst” phone number to ensure that it is correct. Also, try sending messages to an alternative number to ensure that all other parts of your application are working.
These are the other error code.
/** TP-Status: no status received. */
public static final int STATUS_NONE = -1;
/** TP-Status: complete. */
public static final int STATUS_COMPLETE = 0;
/** TP-Status: pending. */
public static final int STATUS_PENDING = 32;
/** TP-Status: failed. */
public static final int STATUS_FAILED = 64;
I'm working auto call recorder app, I'm able to record voice call on below android 6 using MediaRecorder.AudioSource.VOICE_CALL,
From android 6 not able to record voice call using VOICE_CALL. I managed to record using MediaRecorder.AudioSource.MIC but here incoming voice not getting recorded and I want to record voice call in normal mode not in speaker on mode. Please help me on this. (I had tried on Xiomi Redmi 4a(android 6),not working).
myRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
myRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
myRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
myRecorder.setMaxDuration(60 * 60 * 1000);
AudioManager audiomanager =
(AudioManager)getSystemService(AUDIO_SERVICE);
audiomanager.setMode(2);
Edit : There is no issue with permissions.
Update : Anyone knows how to forcing another stream to MIC audio source. This requires native android code. Please help me on this
Refer this question for more details on routing audio
You need to use ndk. Here are examples of the functions that need to be done.
Load libmedia.so and libutils.so
int load(JNIEnv *env, jobject thiz) {
void *handleLibMedia;
void *handleLibUtils;
int result = -1;
lspr func = NULL;
pthread_t newthread = (pthread_t) thiz;
handleLibMedia = dlopen("libmedia.so", RTLD_NOW | RTLD_GLOBAL);
if (handleLibMedia != NULL) {
func = dlsym(handleLibMedia, "_ZN7android11AudioSystem13setParametersEiRKNS_7String8E");
if (func != NULL) {
result = 0;
}
audioSetParameters = (lasp) func;
} else {
result = -1;
}
handleLibUtils = dlopen("libutils.so", RTLD_NOW | RTLD_GLOBAL);
if (handleLibUtils != NULL) {
fstr = dlsym(handleLibUtils, "_ZN7android7String8C2EPKc");
if (fstr == NULL) {
result = -1;
}
} else {
result = -1;
}
cmd = CM_D;
int resultTh = pthread_create(&newthread, NULL, taskAudioSetParam, NULL);
return result;}
Function setParameters
int setParam(jint i, jint as) {
pthread_mutex_lock(&mt);
audioSession = (int) (as + 1);
kvp = "input_source=4";
kvps = toString8(kvp);
cmd = (int) i;
pthread_cond_signal(&cnd);
pthread_mutex_unlock(&mt);
return 0;}
Task AudioSetParameters
void *taskAudioSetParam(void *threadid) {
while (1) {
pthread_mutex_lock(&mt);
if (cmd == CM_D) {
pthread_cond_wait(&cnd, &mt);
} else if (audioSetParameters != NULL) {
audioSetParameters(audioSession, kvps);
}
pthread_mutex_unlock(&mt);
}
}
There is a library and an example of use https://github.com/ViktorDegtyarev/CallRecLib
Xiaomi devices always have problems with permission request even run-time or install-time.
I have an Xiaomi Redmi 3 pro, and it always force to Deny some permission when I install apps, so I must manually Allow it.
If your problem is the same, I found some workaround solution and it worked for me: How to get MIUI Security app auto start permission programmatically?
First these 3 permissions are needed in Manifest as well as a runtime permission request if the device is above Marshmallow,
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" />
MediaRecorder.AudioSource.VOICE_CALL is not supported on all phones so you need to continue using MediaRecorder.AudioSource.MIC.
I use this and works fine on most of the devices,
recorder = new MediaRecorder();
recorder.setAudioSource(audioSource);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(your_path);
You need to set this to record your calls properly,
audioManager.setMode(AudioManager.MODE_IN_CALL);
raise volume level when you start recording
audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL,audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL), 0);
When you stop recording set the mode to normal,
audioManager.setMode(AudioManager.MODE_NORMAL); and also set the stream volume to back how it was.
This could be a Permission related issue.
With the introduction of Android 6.0 Marshmallow, the app will not be granted any permission at installation time. Instead, the application has to ask the user for a permission one-by-one at run-time.
I hope you have included the code which explicitly asks for permissions on devices with Marshmallow and above.
In automatic call recorder (callU) have a option "SoundFX" If Enable Record Calls Two Side
Link
try
MediaRecorder.AudioSource.VOICE_COMMUNICATION
and see
https://androidforums.com/threads/android-phone-with-call-recording-function.181663/
Status: not solved yet
Problem
Once I build and install an app with GearVR it asks by default:
XXX is requesting permission to access photos, media and files on your device. Allow?
Allow / Deny
I don't need my app to access any of those above. How can I get rid of this programmatically?
Edit 1
It seems that Unity automatically adds READ_EXTERNAL_STORAGE to any build for some reason. Stripping out the permission doesn't help in newer versions of Unity as the build fails with the message:
Unable to merge android manifests...
Edit 2
The OVRPlugin causes this issue and at the moment.
https://forum.unity3d.com/threads/how-to-remove-android-permission-read_external_storage.429369/
Unity forums say it is unlikely to fix. Maybe there are still some workarounds?
Edit 3
Oculus is working on it, we should receive a fix in February
https://forums.oculus.com/developer/discussion/42465/is-android-permission-read-external-storage-a-must-when-using-unity#latest
I stumble upon this some time ago and still not sure why Unity builds ask for those permissions. Anyway to get rid of them you can use an editor script as a workaround:
protected void BuildAPKCustom(string buildPath)
{
bool manifestFileExists = false;
if(File.Exists(Path.Combine(Application.dataPath, "Plugins/Android/AndroidManifest.xml")))
{
manifestFileExists = true;
File.Copy(Path.Combine(Application.dataPath, "Plugins/Android/AndroidManifest.xml"), Path.Combine(Application.dataPath, "Plugins/Android/tmpManifestFile.xml"));
File.Delete(Path.Combine(Application.dataPath, "Plugins/Android/AndroidManifest.xml"));
}
string[] levels = new string[EditorSceneManager.sceneCount];
for (int i = 0; i < levels.Length; i++)
{
levels[i] = EditorSceneManager.GetSceneAt(i).path;
}
BuildPipeline.BuildPlayer(levels, buildPath, BuildTarget.Android, BuildOptions.None);
XNamespace android = "http://schemas.android.com/apk/res/android";
string generatedXMLFilePath = Path.Combine(Application.dataPath, "../Temp/StagingArea/AndroidManifest.xml");
XDocument doc = XDocument.Load(generatedXMLFilePath);
IEnumerable<XElement> permissionElements = doc.Root.Elements("uses-permission");
foreach(XElement permission in permissionElements)
{
int potentialIndex = PERMISSIONS_NAMES_TO_DELETE.IndexOf(permission.Attribute(android + "name").Value.Replace("android.permission.", ""));
if(potentialIndex >= 0)
{
UnityEngine.Debug.Log("Permission deleted : " + PERMISSIONS_NAMES_TO_DELETE[potentialIndex]);
permission.Remove();
}
}
XElement overwritenPermission;
for(int i = 0; i < PERMISSIONS_NAMES_TO_DELETE.Length; i++)
{
overwritenPermission = new XElement("uses-permission");
overwritenPermission.Add(new XAttribute(android + "name", "android.permission." + PERMISSIONS_NAMES_TO_DELETE[i]));
overwritenPermission.Add(new XAttribute(android + "maxSdkVersion", "18"));
doc.Element("manifest").Add(overwritenPermission);
}
if(!Directory.Exists(Path.Combine(Application.dataPath, "Plugins/Android")))
{
Directory.CreateDirectory(Path.Combine(Application.dataPath, "Plugins/Android"));
}
doc.Save(Path.Combine(Application.dataPath, "Plugins/Android/AndroidManifest.xml"));
BuildPipeline.BuildPlayer(levels, buildPath, BuildTarget.Android, BuildOptions.None);
if(manifestFileExists)
{
File.Delete(Path.Combine(Application.dataPath, "Plugins/Android/AndroidManifest.xml"));
File.Copy(Path.Combine(Application.dataPath, "Plugins/Android/tmpManifestFile.xml"), Path.Combine(Application.dataPath, "Plugins/Android/AndroidManifest.xml"));
File.Delete(Path.Combine(Application.dataPath, "Plugins/Android/tmpManifestFile.xml"));
}
Process.Start(Path.GetDirectoryName(buildPath));
}
(PERMISSIONS_NAMES_TO_DELETE being a string[] of the permissions names to delete. To get the permissions names list you can look here)
What it does is:
get the previous AndroidManifest.xml file (if it exists) in /Android/Plugins/ folder, copy it to a temporary one and delete it
perform a first build to let Unity generate an AndroidManifest.xml file on his own
edit the manifest to "delete" unnecessary permissions
save the edited manifest to /Android/Plugins/
perform a second build with a correctly set manifest
The idea behind the permission deletion is to set the maximum API level to such a lower level, the permissions will not be usable (please note the permission MUST exists at this API level).
Hope this helps,
I'm having trouble trying to access most of the stats from my Android device's battery such as BATTERY_PROPERTY_CAPACITY, BATTERY_PROPERTY_CHARGE_COUNTER or BATTERY_PROPERTY_CURRENT_AVERAGE. These properties are all clearly documented here: http://developer.android.com/reference/android/os/BatteryManager.html
I have the following permission declared on my manifest:
<uses-permission android:name="android.permission.BATTERY_STATS" />
I have a non-null BatteryManager instance:
mBatteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE);
And whenever I try to retrieve these stats:
double remainingCapacity = mBatteryManager.getIntProperty(
BatteryManager.BATTERY_PROPERTY_CAPACITY);
double batteryCapacityMicroAh = mBatteryManager.getIntProperty(
BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER);
double averageCurrentMicroA = mBatteryManager.getIntProperty(
BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE);
The results are all 0 for all of those. Always, without fail, 0. I've tried this on an emulator, an actual device, and everything I've thought of has failed to modify my results.
I'd greatly appreciate any help. Ultimately, what I'm trying to do is calculate the time remaining for a device to reach its full charge (while charging). Thanks in advance.
Not sure if this is any help for you now, but only phones that have a battery fuel gauge (https://source.android.com/devices/tech/power/device.html) can report back some of the values you are looking for. AFAIK, only the Nexus 6, 9, and 10 gives all three values you are looking for, with Nexus 5 giving only BATTERY_PROPERTY_CAPACITY.
You need to register for Action_Battery_Changed broadcast . This will get invoked whenever this event occurs. Since this is a sticky Intent, it keeps on broadcasting once registered. The method below would get the current level of battery.
private void getBatteryPercentage() {
BroadcastReceiver batteryLevelReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
context.unregisterReceiver(this);
int currentLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
int level = -1;
if (currentLevel >= 0 && scale > 0) {
level = (currentLevel * 100) / scale;
}
Toast.makeText(MainActivity.this, level + "%", Toast.LENGTH_LONG).show();
}
};
IntentFilter batteryLevelFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(batteryLevelReceiver, batteryLevelFilter);
}
Value of BatteryManager.EXTRA_LEVEL is current battery capacity.
I guess you are looking for the total capacity(full), you need to read /sys/class/power_supply/battery/charge_full_design or charge_full, different manufacturers may have different path.
Works real device api 30, without permission
val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val capacity = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
val counter = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
val average = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE)