PackageInstaller does not work on MIUI optimization mode - miui

I created a test application for installing apk files. PackageInstaller was used for this. The app works well. However, for Xiaomi in BroadcastReceiver I get the "INSTALL_FAILED_INTERNAL_ERROR: Permission Denied" error. But if you enable developer mode and disable MIUI optimization, then the application also successfully installs packages. I can't get users of my application to force them to turn off the optimization mode, how can I deal with this? Tested on MIUI 11 version

You can detect whether user has MIUI and optimization mode enabled and display a message which will force user to disable it. Use these utility methods (it's a part of Split APKs Installer source code): https://github.com/Aefyr/SAI/blob/master/app/src/main/java/com/aefyr/sai/utils/MiuiUtils.java

It seems as though MIUI 20.2.20 solves this incompatibility. solru's answer checks for this.
In case the GitHub link stops working:
public static boolean isMiui() {
return !TextUtils.isEmpty(Utils.getSystemProperty("ro.miui.ui.version.name"));
}
public static String getMiuiVersionName() {
String versionName = Utils.getSystemProperty("ro.miui.ui.version.name");
return !TextUtils.isEmpty(versionName) ? versionName : "???";
}
public static int getMiuiVersionCode() {
try {
return Integer.parseInt(Objects.requireNonNull(Utils.getSystemProperty("ro.miui.ui.version.code")));
} catch (Exception e) {
return -1;
}
}
public static String getActualMiuiVersion() {
return Build.VERSION.INCREMENTAL;
}
private static int[] parseVersionIntoParts(String version) {
try {
String[] versionParts = version.split("\\.");
int[] intVersionParts = new int[versionParts.length];
for (int i = 0; i < versionParts.length; i++)
intVersionParts[i] = Integer.parseInt(versionParts[i]);
return intVersionParts;
} catch (Exception e) {
return new int[]{-1};
}
}
/**
* #return 0 if versions are equal, values less than 0 if ver1 is lower than ver2, value more than 0 if ver1 is higher than ver2
*/
private static int compareVersions(String version1, String version2) {
if (version1.equals(version2))
return 0;
int[] version1Parts = parseVersionIntoParts(version1);
int[] version2Parts = parseVersionIntoParts(version2);
for (int i = 0; i < version2Parts.length; i++) {
if (i >= version1Parts.length)
return -1;
if (version1Parts[i] < version2Parts[i])
return -1;
if (version1Parts[i] > version2Parts[i])
return 1;
}
return 1;
}
public static boolean isActualMiuiVersionAtLeast(String targetVer) {
return compareVersions(getActualMiuiVersion(), targetVer) >= 0;
}
#SuppressLint("PrivateApi")
public static boolean isMiuiOptimizationDisabled() {
if ("0".equals(Utils.getSystemProperty("persist.sys.miui_optimization")))
return true;
try {
return (boolean) Class.forName("android.miui.AppOpsUtils")
.getDeclaredMethod("isXOptMode")
.invoke(null);
} catch (Exception e) {
return false;
}
}
public static boolean isFixedMiui() {
return isActualMiuiVersionAtLeast("20.2.20") || isMiuiOptimizationDisabled();
}
Ultimately the functions you're looking for are isMiui and isMiuiFixed.

Related

Worker stop in the middle and not updating progress bar

I'm trying to load information with worker and using reportprogress to update progress bar until finshing, but the worker stop working and doesn't finish the for loop or continue after several minutes. I don't know what's the problem and I tried every post here I can find related to this problem and didn't get anything. I hope I can finally get an answer posting my problem here.
Here's the relevant code:
public class Class1
{
public BackgroundWorker unit_read_data_setting_Worker;
public Class1()
{
unit_read_data_setting_Worker = new BackgroundWorker();
unit_read_data_setting_Worker.WorkerReportsProgress = true;
unit_read_data_setting_Worker.WorkerSupportsCancellation = false;
unit_read_data_setting_Worker.DoWork += new DoWorkEventHandler(unit_read_data_setting);
unit_read_data_setting_Worker.ProgressChanged += new ProgressChangedEventHandler(_update_progress);
unit_read_data_setting_Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Completed);
}
public void unit_read_data_setting(object sender = null, DoWorkEventArgs e = null)
{
lock (FamilyTreeViewModel.Lock_ParameterList)
{
ObservableCollection<Parameter_UC_ViewModel> _internal_parameter_list =
FamilyTreeViewModel.GetInstance.ParameterList;
if (FamilyTreeViewModel.GetInstance.SelectedUnitSetting != null)
{
if (_internal_parameter_list.Count > 0)
{
for (int i = 0; i < _internal_parameter_list.Count; i++)
{
int startValue = i * 100 / _internal_parameter_list.Count;
unit_read_data_setting_Worker.ReportProgress(startValue);
// do stuff related to the index
// when progress_bar at 76 value, the loop stoppes and cotinue after a minute
}
}
}
}
}
private void _update_progress(object sender, ProgressChangedEventArgs e)
{
FamilyTreeViewModel.GetInstance.Unit_read_data_setting_progress_bar = e.ProgressPercentage;
}
private void Completed(object sender, RunWorkerCompletedEventArgs e)
{
// never gets here but there's no error
}
}

How to avoid java.util.NoSuchElementException

The code below is giving me the error java.util.NoSuchElementException right after I Ctrl+Z
to indicate that the user input is complete. By the looks of it seems as if it does not know how to just end one method without messing with the other scanner object.
I try the hasNext method and I ended up with an infinite loop, either way is not working. As a requirement for this assignment I need to be able to tell the user to use Ctrl+Z or D depending on the operating system. Also I need to be able to read from a text file and save the final tree to a text file please help.
/* sample input:
CSCI3320
project
personal
1 HW1
1 HW2
1 2 MSS.java
2 p1.java
*/
import java.util.Scanner;
import java.util.StringTokenizer;
public class Directory {
private static TreeNode root = new TreeNode("/", null, null);
public static void main(String[] args) {
userMenu();
System.out.println("The directory is displayed as follows:");
root.listAll(0);
}
private static void userMenu(){ //Displays users menu
Scanner userInput = new Scanner(System.in);//Scanner option
int option = 0;
do{ //I believe the problem is here since I am not using userInput.Next()
System.out.println("\n 1. add files from user inputs ");
System.out.println("\n 2. display the whole directory ");
System.out.println("\n 3. display the size of directory ");
System.out.println("\n 0. exit");
System.out.println("\n Please give a selection [0-3]: ");
option = userInput.nextInt();
switch(option){
case 1: addFileFromUser();
break;
case 2: System.out.println("The directory is displayed as follows:");
root.listAll(0);
break;
case 3: System.out.printf("The size of the directory is %d.\n", root.size());
break;
default:
break;
}
}while( option !=0);
userInput.close();
}
private static void addFileFromUser() {
System.out.println("To terminate inp1ut, type the correct end-of-file indicator ");
System.out.println("when you are prompted to enter input.");
System.out.println("On UNIX/Linux/Mac OS X type <ctrl> d");
System.out.println("On Windows type <ctrl> z");
Scanner input = new Scanner(System.in);
while (input.hasNext()) { //hasNext being used Crtl Z is required to break
addFileIntoDirectory(input); // out of the loop.
}
input.close();
}
private static void addFileIntoDirectory(Scanner input) {
String line = input.nextLine();
if (line.trim().equals("")) return;
StringTokenizer tokens = new StringTokenizer(line);
int n = tokens.countTokens() - 1;
TreeNode p = root;
while (n > 0 && p.isDirectory()) {
int a = Integer.valueOf( tokens.nextToken() );
p = p.getFirstChild();
while (a > 1 && p != null) {
p = p.getNextSibling();
a--;
}
n--;
}
String name = tokens.nextToken();
TreeNode newNode = new TreeNode(name, null, null);
if (p.getFirstChild() == null) {
p.setFirstChild(newNode);
}
else {
p = p.getFirstChild();
while (p.getNextSibling() != null) {
p = p.getNextSibling();
}
p.setNextSibling(newNode);
}
}
private static class TreeNode {
private String element;
private TreeNode firstChild;
private TreeNode nextSibling;
public TreeNode(String e, TreeNode f, TreeNode s) {
setElement(e);
setFirstChild(f);
setNextSibling(s);
}
public void listAll(int i) {
for (int k = 0; k < i; k++) {
System.out.print('\t');
}
System.out.println(getElement());
if (isDirectory()) {
TreeNode t = getFirstChild();
while (t != null) {
t.listAll(i+1);
t = t.getNextSibling();
}
}
}
public int size() {
int s = 1;
if (isDirectory()) {
TreeNode t = getFirstChild();
while (t != null) {
s += t.size();
t = t.getNextSibling();
}
}
return s;
}
public void setElement(String e) {
element = e;
}
public String getElement() {
return element;
}
public boolean isDirectory() {
return getFirstChild() != null;
}
public void setFirstChild(TreeNode f) {
firstChild = f;
}
public TreeNode getFirstChild() {
return firstChild;
}
public void setNextSibling(TreeNode s) {
nextSibling = s;
}
public TreeNode getNextSibling() {
return nextSibling;
}
}
}
Exception Details:
/*Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:907)
at java.util.Scanner.next(Scanner.java:1530)
at java.util.Scanner.nextInt(Scanner.java:2160)
at java.util.Scanner.nextInt(Scanner.java:2119)
at Directory.userMenu(Directory.java:36)
at Directory.main(Directory.java:21)*/
Your problem is this line:
option = userInput.nextInt(); //line 24
If you read the Javadoc, you will find that the nextInt() method can throw a NoSuchElementException if the input is exhausted. In other words, there is no next integer to get. Why is this happening in your code? Because you this line is in a loop once that first iteration completes (on the outer while loop) your initial input selection has been consumed. Since this is a homework, I am not going to write the code. But, if you remove the loop, you know this works at least once. Once you try to loop, it breaks. So I will give you these hints:
Change the do/while to a while loop.
Prompt the user once outside the loop.
Recreate the prompt and recapture the user input inside the loop.
For example, the code below can be used for the basis of your outer loop.
import java.util.Scanner;
public class GuessNumberGame {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Guess the secret number: (Hint: the secret number is 1)");
int guess = input.nextInt();
while (guess != 1) {
System.out.println("Wrong guess. Try again: ");
guess = input.nextInt();
}
System.out.println("Success");
input.close();
}
}
The reason why this works is because I don't reuse the same, exhausted, scanner input object to get the next integer. In your example, the initial input is inside the loop. The second time around, that input has already been consumed. Follow this pattern and you should be able to complete your assignment.

how to generate sequence number using c# in window application

private string GenerateID()
{
}
private void auto()
{
AdmissionNo.Text = "A-" + GenerateID();
}
with prefix of A like below
A-0001
A-0002 and so on .
You can use below code.
private string GenerateId()
{
int lastAddedId = 8; // get this value from database
string demo = Convert.ToString(lastAddedId + 1).PadLeft(4, '0');
return demo;
// it will return 0009
}
private void Auto()
{
AdmissionNo.Text = "A-" + GenerateId();
// here it will set the text as "A-0009"
}
Look at this
public class Program
{
private static int _globalSequence;
static void Main(string[] args)
{
_globalSequence = 0;
for (int i = 0; i < 10; i++)
{
Randomize(i);
Console.WriteLine("----------------------------------------->");
}
Console.ReadLine();
}
static void Randomize(int seed)
{
Random r = new Random();
if (_globalSequence == 0) _globalSequence = r.Next();
Console.WriteLine("Random: {0}", _globalSequence);
int localSequence = Interlocked.Increment(ref _globalSequence);
Console.WriteLine("Increment: {0}, Output: {1}", _globalSequence, localSequence);
}
}
Whether it is an windows application or not is IMHO not relevant. I'd rather care about thread safety. Hence, I would use something like this:
public sealed class Sequence
{
private int value = 0;
public Sequence(string prefix)
{
this.Prefix = prefix;
}
public string Prefix { get; }
public int GetNextValue()
{
return System.Threading.Interlocked.Increment(ref this.value);
}
public string GetNextNumber()
{
return $"{this.Prefix}{this.GetNextValue():0000}";
}
}
This could easily be enhanced to use the a digit count. So the "0000" part could be dynamically specified as well.

Console project fails with console.writeline but not console.readline

I have a small sample program which breaks when it reaches line 50 with "Error CS1513: } expected". It's typical, except that I counted the number of curly brackets over and over and found no error. I was told on another forum that the problem is probably my placement of the using keyword and class declarations, but I couldn't find anything wrong.
I would like to know if I'm making a mistake. This is the entire program; written with SharpDevelop if it makes any difference.
using System;
namespace Problem
{
public class ClassA
{
public static void Main(string[] args)
{
ClassB MyObject = new ClassB();
MyObject.MethodA();
}
}
public class ClassB
{
public String str_a = "";
public String str_b = "";
public String str_c = "";
public bool bool_a = false;
public int[] int_a = new int[6];
public void MethodA()
{
while (str_a == "" || str_a == null)
{
String str_a2 = Console.ReadLine();
if (str_a2 == "" || str_a2 == null)
{
}
else
{
str_a = str_a2;
}
}
while (str_c == "")
{
String str_c2 = Console.ReadLine();
if (str_c2 == "" || str_c2 == null)
{
}
else
{
str_c = str_c2;
}
}
while (bool_a == false)
{
Console.WriteLine(""); //Fails to compile, asks for ending brackets here
for (int i = 0; i < 6; i += 1)
{
int_a[i] = 0;
}
bool_a = true;
}
}
}
}
I'm pretty sure you could be a victim of UNICODE quotes.
ʺ ̋“”″"
Try just removing the double-quote characters and typing them in your code editor.
Doh! Classic error! I had a declaration in a while loop:
while {
public int[] int_b = new int[6];
}
Sorry about that, SO. I was having one of those days...

List getting threadsafe with removing items

I'm trying to remove items from a list until its empty with multithreading.
Code:
public void testUsers() {
final List<User> users = userDao.findAll();
final int availableProcessors = Runtime.getRuntime().availableProcessors() * multiplier;
final List<String> loggingList = Lists.newArrayList();
final List<Integer> sizeChecked = Lists.newArrayList();
int totalSizeChecked = 0;
int sizeList = users.size();
ExecutorService executorService = Executors.newFixedThreadPool(availableProcessors);
for (int i = 0; i < availableProcessors; i++) {
createThread(executorService, users, loggingList, sizeChecked);
}
executorService.shutdown();
try {
// wait for all threads to die
executorService.awaitTermination(1, TimeUnit.HOURS);
} catch (InterruptedException ex) {
}
for (Integer count : sizeChecked) {
totalSizeChecked += count;
}
Assert.assertTrue(totalSizeChecked==sizeList);
}
private void createThread(ExecutorService executorService, final List<User> users,
final Collection<String> loggingList, final List<Integer> sizeChecked) {
executorService.execute(new Runnable() {
#Override
public void run() {
int totalChecked = 0;
while (!users.isEmpty()) {
User user = null;
synchronized (users) {
if (!users.isEmpty()) {
user = users.remove(0);
}
}
totalChecked++;
if (user != null) {
String reason = checkUser(user);
if (reason != null) {
loggingList.add(reason);
}
} else {
LOGGER.info("user is null");
}
}
sizeChecked.add(totalChecked);
}
});
}
Now I was thinking this couldn't be so wrong cause I made the list synchronised for removing the first item.
I'm testing with a multiplier of 6.(on prod it will be lowered to 1-2)
I get this in the email :
The batch was not correctly executed.
Size of accounts that must be checked : 28499. Size of accounts that have been checked: 25869
What do I wrong to get it threadsafe?
List<Integer> sizeChecked is not thread safe. Therefore you cannot add elements in parallel in it.
Synchronize your add operation or use a thread-safe structure. If sizeChecked is just a counter, use an AtomicLong instead and make each thread increment it.

Resources