Check permissions on xiaomi device with a version below api 23 - android

As you know, Xiaomi devices have their own system of permissions. I'm testing my application on the device xiaomi redmi 3, api 22, android 5.1.1. I want to check if there is permission to access the camera and audio. But the standard way does not work:
ContextCompat.checkSelfPermission(getActivity().getApplicationContext(), "android.permission.CAMERA");
returns 0, although this is not true.
I found another way, but it also does not work correctly:
boolean b = hasSelfPermissionForXiaomi(getActivity(),"android.permission.CAMERA");
private boolean hasSelfPermissionForXiaomi(Context context,String permission){
String permissionTop = AppOpsManagerCompat.permissionToOp(permission);
if(permissionTop == null){
// not dangerous
return true;
}
int noteOp = AppOpsManagerCompat.noteOp(context,permissionTop, Process.myUid(),context.getPackageName());
return noteOp == AppOpsManagerCompat.MODE_ALLOWED && checkSelfPermission(context,permission) == PackageManager.PERMISSION_GRANTED;
}
b = true, although this is not true.
Guys, did any of you understand how to check permissions on xiaomi devices ???

Related

How to detect that Android device doesn't have built-in battery?

Some of my users have head unit devices on Android (in their cars) and of course such device doesn't have battery and the next code returns 0
val batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
and the next method will return false
val status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
val statusCharging = status == BatteryManager.BATTERY_STATUS_CHARGING
I have a video recording app and it stops recording automatically if batteryLevel <= 1 && !statusCharging
And it stops recording for such devices which don't have any battery
You can use BatteryManager.EXTRA_PRESENT which according to the documentation, exposes a:
boolean indicating whether a battery is present.

SMS manager not working on specific devices

I'm developing an application in which i can send specific messages to specific number.
the messages are already pre-defined for example "SYSSTAT", and number is also pre-define when user start application he/she enter receiver device number.
But i'm getting error as SMSManager returns RESULT_ERROR_GENERIC_FAILURE, i had tested on various OS like start from Marshmallow to Pie but i'm getting error only on Marshmallow devices.
I had already give each permission manually too, but unfortunately not work on marshmallow devices only i had checked on Redmi 4A, Note 7 pro, Note 7, Nokia 6.1, etc...
Kindly help me.
It's due to simInfo.subscriptionId
here is sample code hwo i manage it.
val activeList = subscriptionManager.activeSubscriptionInfoList
if (activeList != null && activeList.isNotEmpty()) {
isMultipleSubscriptions = activeList.size > 1
val simInfo1 = activeList[0] as SubscriptionInfo
val simInfo2 = activeList[1] as SubscriptionInfo
if (simInfo1.displayName != null && simInfo1.displayName != "") {
companies.add(simInfo1.displayName.toString())
companySubscriptionId.add(simInfo1.subscriptionId)
}
if (simInfo2.displayName != null && simInfo2.displayName != "") {
companies.add(simInfo2.displayName.toString())
companySubscriptionId.add(simInfo2.subscriptionId)
}
}
And send SMS using selected subscription id
SmsManager.getSmsManagerForSubscriptionId(aSubscriptionId)
.sendTextMessage(
phoneNumber,
null,
aMsg,
sentPI,
deliveredPI
)

Android Call Recording Incoming voice not getting recorded

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/

How to know a process of an app is 32-bit or 64-bit programmatically in Android lollipop?

As we all know from Android 5.0.64bit support is there. I have very simple question. Can we check programmatically in what mode any application is running i.e. 32bit or 64bit? For example: I have Facebook app running on my Nexus 9, so can I check using my android app if Facebook app's process is running in 32bit mode or 64bit mode?
In Nexus 5x
String arch = System.getProperty("os.arch");
returns
armv8l
it is not aarch64 and my code broke. However,
root#bullhead:/ # uname -m
aarch64
root#bullhead:/ # getprop ro.product.cpu.abilist
arm64-v8a,armeabi-v7a,armeabi
Wired. So I changed my code to
boolean is64 = (android.os.Build.VERSION.SDK_INT >= 21) && System.getProperty("ro.product.cpu.abilist").contains("64");
Updated on 2016-02-11
In Samsung Samsung Galaxy S5 Neo, Android 5.1.1
String arch = System.getProperty("os.arch");
returns aarch64 but it is not 64-bit device!!!
ro.product.cpu.abilist returns armeabi-v7a,armeabi
bool is64Bit = System.getProperty("ro.product.cpu.abilist").contains("64");
check is the only way to check.
Try System.getProperty("os.arch").
I haven't tried it on 64-bit android, but it must return something like 'aarch64' in case of 64 bit device.
http://developer.android.com/reference/java/lang/System.html#getProperty(java.lang.String)
public static boolean is64Bit() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//Added in API level 23
return Process.is64Bit();
}
try {
Class cls = Class.forName("dalvik.system.VMRuntime");
Method getRuntimeMethod = cls.getDeclaredMethod("getRuntime");
Object vmRuntime = getRuntimeMethod.invoke(null);
Method is64BitMethod = cls.getDeclaredMethod("is64Bit");
Object is64Bit = is64BitMethod.invoke(vmRuntime);
if (is64Bit instanceof Boolean) {
return (boolean) is64Bit;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
IMO, you can use reflect to get the result of is64Bit. Android 6.0 began to provide this api to check your process.
android.os.Process.is64Bit()
In my experience (if your minSdkVersion is >= 21) the best way is to check the size of the array Build.SUPPORTED_64_BIT_ABIS.
(see https://developer.android.com/reference/android/os/Build#SUPPORTED_64_BIT_ABIS)
Something like this:
public static boolean is64Bit() {
return (Build.SUPPORTED_64_BIT_ABIS!= null && Build.SUPPORTED_64_BIT_ABIS.length >0);
}
What makes you think your device isn't 64-bit? The specs for the phone indicate it uses an Exynos 7 Octa 7580 which is arm8 and 64-bit.
boolean is64Arch = Build.CPU_ABI.equalsIgnoreCase("x86_64") || Build.CPU_ABI.equalsIgnoreCase("arm64-v8a");

android is it possible for an app to detect when it is running on emulator vs device

I develop a game that is heavily dependent upon timing, when I run it in the emulator it executes understandably slower than when I run it on my phone. This forces me to up all the "stats" in my game, so that I can actually "beat it" when I am developing - when Debugging, the game is unwinnable.
Is there a call, or variable, or something that I can use to determine whether I am currently running on the Emulator and not a device.
I've considered trying to detect if Framerate is low.
I've considered trying to read the "device name" from some sort of build in system field.
But neither seems like a very good method to pursue.
Any help would be great.
Use the Build.DEVICE value and compare to "sdk".
First idea:check the network operator, on the emulator, it's always equal to "Android". Not documented and just a guess that it will work everytime!
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String networkOperator = tm.getNetworkOperatorName();
if("Android".equals(networkOperator)) {
// Emulator
}
else {
// Device
}
Second idea: the manufacturer:
public boolean isEmulator() {
return Build.MANUFACTURER.equals("unknown");
}
Third idea: seem th best one, check the debug key:
static final String DEBUGKEY =
"get the debug key from logcat after calling the function below once from the emulator";
public static boolean signedWithDebugKey(Context context, Class<?> cls)
{
boolean result = false;
try {
ComponentName comp = new ComponentName(context, cls);
PackageInfo pinfo = context.getPackageManager().getPackageInfo(comp.getPackageName(),PackageManager.GET_SIGNATURES);
Signature sigs[] = pinfo.signatures;
for ( int i = 0; i < sigs.length;i++)
Log.d(TAG,sigs[i].toCharsString());
if (DEBUGKEY.equals(sigs[0].toCharsString())) {
result = true;
Log.d(TAG,"package has been signed with the debug key");
} else {
Log.d(TAG,"package signed with a key other than the debug key");
}
} catch (android.content.pm.PackageManager.NameNotFoundException e) {
return false;
}
return result;
}
from here: How can I detect when an Android application is running in the emulator?
If you're using Google APIs, you want:
"google_sdk".equals( Build.PRODUCT );
If not, you'll want to use:
"sdk".equals( Build.PRODUCT );
The older (since deprecated) way to do this was to check ANDROID_ID, which is null on the AVD, but this doesn't work on API 7 and above:
// ONLY WORKS ON 2.1 AND BELOW
String android_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
if (android_id == null) {
// Emulator!
} else {
// Device
}
Dan S gave a good answer about how to detect when running on the emulator. However, a few tips:
Instead of relying on something in the SDK, why not just set up your own flag? Just keep a public final static boolean isEmulator that you change from true to false depending on the environment, and build your code with ifs and elses around it. The Build.DEVICE method is not 100% safe, since some rooted devices might have that borked.
Low framerate detection could be a good thing to implement. Given the wide range of Android devices, it might prove helpful on lower-end ones.

Categories

Resources