I've got a problem with realm and his method setDefaultConfiguration.
Indeed, my app is multi user, and I need to switch between several realm configurations.
During the main activity loading, I configure the realm configuration like this:
String bddName = String.format("%s.realm",userID);
userFolder = new File(getApplicationContext().getFilesDir() + "/" + userID);
config = new RealmConfiguration.Builder(userFolder)
.name(bddName)
.schemaVersion(2)
.migration(new RealmMigration2())
.build();
Realm.setDefaultConfiguration(config);
But, If I try to configure it twice with the same config, Realm send me an error:
Configurations cannot be different if used to open the same file.
Is it possible to test whether the current configuration is different from the one I want to set?
I've tried :
if(!config.equals(Realm.getDefaultInstance().getConfiguration()))
But at the first launch of the Activity, Realm return an error, because no default instance is set.
I'm turning around because it's impossible to test the realm configuration before setting it.
Could you help me ?
Thank you a lot.
Edit :
this solution doesn't work too, i've got the same error, however, the RealmFileName are different:
try{
//first time, Realm is not configure, so It's catched.
//else, it set the default config only if the config is different
if(!config.getRealmFileName().equals(Realm.getDefaultInstance().getConfiguration().getRealmFileName())){
Realm.setDefaultConfiguration(config);
}
}
catch (Exception e){
Realm.setDefaultConfiguration(config);
}
The problem is that you are creating two instances of the RealmMigration2 class. If you don't override equals in your class:
RealmMigration migration1 = new RealmMigration2();
RealmMigration migration2 = new RealmMigration2();
migration1.equals(migration2) == false
Which will cause the comparison of RealmConfigurations to fail.
So you should either make your RealmMigration instance a singleton or override hashCode()/equals().
Related
I've been trying to print with Brother Print SDK 3.5.1 on Android 8.1.0. I keep getting ERROR_WRONG_LABEL.
This is the code I use
void printPdf() {
// Specify printer
final Printer printer = new Printer();
PrinterInfo settings = printer.getPrinterInfo();
settings.printerModel = PrinterInfo.Model.QL_810W;
settings.port = PrinterInfo.Port.NET;
settings.ipAddress = "192.168.1.73";
settings.workPath = "storage/emulated/0/Download/";
// Print Settings
settings.labelNameIndex = LabelInfo.QL700.W62RB.ordinal();
settings.printMode = PrinterInfo.PrintMode.FIT_TO_PAGE;
settings.orientation = PrinterInfo.Orientation.PORTRAIT;
settings.isAutoCut = true;
printer.setPrinterInfo(settings);
// Connect, then print
new Thread(new Runnable() {
#Override
public void run() {
if (printer.startCommunication()) {
PrinterStatus result = printer.printPdfFile("/storage/emulated/0/Download/hello world red.pdf", 1);
if (result.errorCode != PrinterInfo.ErrorCode.ERROR_NONE) {
Log.d("TAG", "ERROR - " + result.errorCode);
}
printer.endCommunication();
}
}
}).start();
}
My printer model is QL-810W and I use the black and red W62 roll.
I've tried the Sample Application, where setting W62RB in labelNameIndex prints fine.
Changing the roll for different one with different width didn't help.
I've also tried iterating over numbers 0 to 50 and using them as labelNameIndex.
Based on this thread, I thought that the issue may be in specifying the workPath attribute. Setting workPath to getContext().getCacheDir().getPath() results in ERROR_OUT_OF_MEMORY instead of ERROR_WRONG_LABEL. Not specifying workPath and adding <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> to AndroidManifest.xml results in ERROR_WRONG_LABEL
EDIT
I've modified the Brother Sample app and uploaded it to GitHub. The app now launches Activity_PrintPdf.java by default where I inserted my printing code with hardcoded values at the beginning of onCreate method - this works fine and prints the PDF file as expected.
Then I created a new Empty Activity project in Android Studio, copy pasted the library, added the imports to build.gradle and copy pasted the permissions into AndroidManifest.xml. Then I copy pasted the printing code at the beginning of onCreate method in MainActivity.java. Running the app results in ERROR_WRONG_LABEL.
This is the modified working example app and this is the one that results in the error. I want to use the code as native module that I call from my React Native app, so it's important that I manage to set up the printing code from scratch rather than modifying the existing example app.
EDIT 2
I've inspected the library with a debugger: when executing printer.setPrinterInfo(mPrinterInfo) the library internally calls private boolean createWorkPath(String dirPath) of Printer object. On return from this method, the debugger shows Source code doesn't match the bytecode and seems to forget the created directory. This also internally sets mResult.errorCode = ErrorCode.ERROR_WORKPATH_NOT_SET. However, instead of rising any error here the code just silently proceeds, which later results in ERROR_WRONG_LABEL when trying to print. Running the same code snipper in the modified Sample app works fine.
I'd be grateful if you could help or suggest what to try next.
Thank you!
I've now fixed the issue, which was that the Brother library silently failed to create a temporarily folder and instead of reporting an error, it continued and failed later to read the label information. Based on this thread, it is now required to specify runtime file read and write permissions as opposed to the compile-time ones in AndroidManifest.xml.
Adding
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
at the beginning of onCreate before the printing code fixed the issue.
I have an app that consumes an API. With every request, I send a header with the version of my app, the server checks it, and if the version is too low, it would throw an error back. I did it like this so that if in the future I introduce breaking changes then I can show a nice message on the app instead of just crashing
Now any request throughout the app can potentially return this error, so what I want to do is catch this globally on every request and close whichever activity is open and open a new one saying some nice message like "Please go to play store to update your app".
Is it possible to do such thing?
To recap, i want to do 2 things:
From any request, generate an ObsoleteAppException through OkHttp/Retrofit
Capture only this exception globally, close any activity and open a new one with the warning
If its any useful, I am using RxJava2 and retrofit
Use Thread.setDefaultUncaughtExceptionHandler in your Application class to catch all exceptions in your app and check if the app should crash or show an update message.
This article Hide your crashes gracefully (and still report them) and many other libraries can help you "Catch exception globally in Android".
As for changing current activity, there are already answers here. It basiclly tracks every activity. When you need to change current activity, just finish current one and start a new one.
This whole approach seems like a bit of overkill for your case but I don't have a better idea...Maybe a custom RxJava exception handler to catch this exception?
You can use UCE Handler to catch exceptions and present the user with options on how to handle it.
In your Project's build.gradle file:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
In your Application's or Module's build.gradle file:
dependencies {
compile 'com.github.jampez77:UCE-Handler:uce_handler:1.4.1'
}
In your Application class initialize library using builder pattern:
public class MyApplication extends Application {
#Override
public void onCreate() {
...
// Initialize UCE_Handler Library
new UCEHandler.Builder(this).build();
}
}
Then make sure you update you manifest as follows:
<application
android:name=".MyApplication"
Good day. The main amazing thing about the BeanShell is the idea that i can control what i want to be done dynamically from the server and i thought it would be amazing.
Although i never succeded in achieving that and seems no one else tried to start activity from the beanshell either.
Here how it goes. I simply want to pass the code from the server side to the Android,Android is going to evaluate that code within interpreter and run that.
The issue is that i am getting the exception from BeanShell no matter what i try.
The code from server side is the next.
$response['method'] = "import my.some.name.*;"
. "startActivity(new Intent(this,MyProfile.class))";
The code for Android is the next.
try {
String responseBody = response.body().string();
JSONObject jsonObject = new JSONObject(responseBody);
String method = jsonObject.optString("method");
Interpreter interpreter = new Interpreter();
try {
Object res = interpreter.eval(method);
} catch (EvalError evalError) {
evalError.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
But i am getting the next exception from the BeanShell
Sourced file: inline evaluation of: ``import my.some.name.*;startActivity(new Intent(this,MyProfile.class));'' : Class: MyProfile not found in namespace : at Line: 1 : in file: inline evaluation of: ``import my.some.name.*;startActivity(new Intent(this,MyProfile.class));'' : MyProfile
Any ideas what is going on?
Just in case if anyone needs the same solution i am posting for everyone to know.
Here how it goes.
Firstly you need to know that whatever you are trying to do on the server side remember that the BeanShell actually does not know anything about the String code you are passing itself,as it is going to interpret it just like a code out of box so with the help of CommonWare hint about full name path i managed to get it working.
So first step to do is to initialize the Interpreter.
Basic initialization goes like this :
String responseBody = response.body().string();
JSONObject jsonObject = new JSONObject(responseBody);
String method = jsonObject.optString("method");
Interpreter interpreter = new Interpreter();
try {
interpreter.set("context",getApplicationContext());
Object res = interpreter.eval(method);
} catch (EvalError evalError) {
evalError.printStackTrace();
}
Take a very attentive notice about the context as it was my main issue going back and forth as at the moment when i succeded to actually force BeanShell recognize my classes,the BeanShell started to throw Method not found exception about the startActivity() so by thinking logically we can assume that we would set the context as activity as the parent one for our remote methods and start evaluating everything from the context. So here how the remote code is looking.
$response['method'] = "import ink.va.activities;"
. "import android.content.Intent;"
. "import android.content.*;"
. "context.startActivity(new android.content.Intent(context, my.package.name.MyProfile.class));";
The most important things to notice here.
• We are importing everything possible for BeanSherll to recognize our classes,even if they are Android-Build,no matter,still we need to import them.
• If you are going to use any class,then as CommonWare noticed out,you MUST specify the full path to that Class E.G my.package.name.MyProfile.class.
• As i was getting Command Not Found i started to think about the context.startActivity() as i have defined the context beforehand in BeanShell as my parent from which i am going to use methods and Woala,everything worked like a charm!
Possible Problems
I don't know a lot about BeanShell, but there's a couple of issues here
You can import a class (in a compiled language) at runtime
You're trying to do the equivalent of Reflection (but aren't doing any)
Security. No user would consent to you having control to open a screen on their app remotely
Presumably BeanShell is supposed to do the reflection under the covers, but in an case you won't be able to do the import.
Possible solutions
The class/activity using the library should import everything (I'm not sure if a compiler will even retain this)
You can use reflection directly, with things like "method from name". The downside is it's very limited what code you can send from the server unless you handle a myriad of cases.
You could only send names/commands; to specific endpoints in your java app (this is what I recommend) and plan the actions you want ahead of time
$response['method'] = "my.some.name.MyProfile";
JSONObject jsonObject = new JSONObject(response.body().string());
String nameParam = jsonObject.optString("method");
Class<? extends Activity> clazz = Class.forName(nameParam); //wrap with try
startActivity( new Intent(this, clazz) )
We are trying to use the library on Android for TimedEviction. The items in the cache are expiring as soon as we overwrite an existing item.
We are building the cache as follows:
private Cache rssiMap;
RemovalListener removalListener = new RemovalListener() {
#Override
public void onRemoval(RemovalNotification removal) {
}
};
rssiMap = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.MINUTES)
.removalListener(removalListener)
.build();
rssiMap.put(device, rssi);
Is there something wrong we are doing with the code or is this a known issue?
This is correct behavior.
Actually, client code doesn't care WHEN the elements are expired, right? Client code does care about WHAT final cache values are.
The RemovalListener focuses on WHAT is evicted instead of WHEN.
JavaDoc of RemovalListener.onRemoval():
Notifies the listener that a removal occurred at some point in the
past.
By the way, I recommend use Cache.get() instead of Cache.put().
From JavaDoc of Cache.put():
Prefer get(Object, Callable) when using the conventional "if cached,
return; otherwise create, cache and return" pattern.
I am trying to get a list of running applications and the amount of battery used by each of them. I have google for a long time but didnt come up with a solution. However there have been a few references on the PowerProfile, PowerUsageSummary internal classes.
I used them through Reflection technique but didnt get what i was looking for. PowerUsageSummary shows the same details as you can see by going to Device Settings->Applications->Battery Use(This is how it can be seen in a Samsund device).
Then i used PowerProfile class but i got only the mA of current utilized by WIFI, AUDIO, VIDEO,GPS, BLUETOOTH etc(The mA values dont change so often. I am not sure if the values are correct). Another reference was the BatteryStatsImpl class. I tested this class but the values are 0 always. Still i am looking for the list of running applications and the amount of battery used by each of them. Any help is appreciated.
Thanks,
Here is the sample code that i tried for BatteryStatsImpl class.
String BATTERY_PROFILE_CLASS = "com.android.internal.os.BatteryStatsImpl";
Object mBatteryProfile = Class.forName(BATTERY_PROFILE_CLASS).getConstructor().newInstance();
Method batteryMeth = Class.forName(BATTERY_PROFILE_CLASS).getMethod("getBatteryUptime", long.class);
Object arglist1[] = new Object[1];
arglist1[0] = System.currentTimeMillis();
// This is to calculate the batteryUpTime since the current time.
Long batteryUptime = (Long) batteryMeth.invoke(mBatteryProfile, arglist1);
Method dischargeMeth = Class.forName(BATTERY_PROFILE_CLASS).getMethod("getDischargeStartLevel");
// This is to calculate the dischargeTime of the device battery
Integer dischargeTime = (Integer) dischargeMeth.invoke(mBatteryProfile);
First please note that you can't make use of this API unless you are installed on the system image and so can hold the BATTERY_STATS permission. This is not available to third part apps installed separately from the system.
To use this, you don't directly instantiate BatteryStatsImpl. You request an instance of it from the current stats being collected by BatteryStatsService. You can look for the source code of the settings app for how to do this: https://code.google.com/p/android-source-browsing/source/browse/src/com/android/settings/fuelgauge/PowerUsageSummary.java?repo=platform--packages--apps--settings
In particular:
import android.os.BatteryStats;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BatteryStatsImpl;
IBatteryStats mBatteryInfo;
UserManager mUm;
BatteryStatsImpl mStats;
mBatteryInfo = IBatteryStats.Stub.asInterface(
ServiceManager.getService("batteryinfo"));
private void load() {
try {
byte[] data = mBatteryInfo.getStatistics();
Parcel parcel = Parcel.obtain();
parcel.unmarshall(data, 0, data.length);
parcel.setDataPosition(0);
mStats = com.android.internal.os.BatteryStatsImpl.CREATOR
.createFromParcel(parcel);
mStats.distributeWorkLocked(BatteryStats.STATS_SINCE_CHARGED);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException:", e);
}
}
the BatteryStatsService maintains the stats. Have a look in there how BatteryStatsImpl is used to do that (those note*() methods are called by the system when e.g. screen turns on)
Maybe you can get the current stats from there