FirebaseVisionImage: variable 'image' might not have been initialized - java

I'm trying to use the example for Google Firebase (machine learning kit) in Android Studio. I'm getting an error when passing the image variable into the detector.processImage method (error shown below).
How can I get past this error? I have to use the FirebaseVisionImage.fromFilePath within a try-catch block, but the error message is telling me that the image variable may not be initialized.
error: variable image might not have been initialized
FirebaseVisionImage image;
try {
image = FirebaseVisionImage.fromFilePath(MainMenuActivity.this,
Uri.fromFile(new File("/sdcard/Download/test.jpg")));
} catch (IOException e) {
e.printStackTrace();
}
FirebaseVisionTextRecognizer detector = FirebaseVision.getInstance().getOnDeviceTextRecognizer();
Task<FirebaseVisionText> result = detector.processImage(image)
.addOnSuccessListener(new OnSuccessListener<FirebaseVisionText>() {
#Override
public void onSuccess(FirebaseVisionText firebaseVisionText) {
// Task completed successfully
mainText.setText("Hello!");
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Task failed with an exception
}
}
);

That error emerges because of this piece of code
FirebaseVisionImage image;
try {
image = FirebaseVisionImage.fromFilePath(
MainMenuActivity.this,
Uri.fromFile(new File("/sdcard/Download/test.jpg"))
);
} catch (IOException e) {
e.printStackTrace();
}
Now, ask yourself, what happens to image if an Exception is thrown inside the try block?
The variable might have been assigned a valid value, or it might have not.
Because you're letting the execution flow to continue (you aren't throwing the Exception to the upper level), the compiler cannot know that for sure, since the exception is thrown at run-time.
And because in Java a local variable must be initialized before usage (even with = null), the compiler is telling you to do so.
error: variable image might not have been initialized
The solution might be to initialize it with null
FirebaseVisionImage image = null;
Or, a better one, to let escape the Exception. That will signal there is a bug.
You'll also be able to completely unwrap your code from the try - catch block.

All code that needs the image should be inside the try block:
try {
FirebaseVisionImage image = FirebaseVisionImage.fromFilePath(MainMenuActivity.this,
Uri.fromFile(new File("/sdcard/Download/test.jpg")));
Task<FirebaseVisionText> result = detector.processImage(image)
.addOnSuccessListener(new OnSuccessListener<FirebaseVisionText>() {
#Override
public void onSuccess(FirebaseVisionText firebaseVisionText) {
// Task completed successfully
mainText.setText("Hello!");
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Task failed with an exception
}
}
);
} catch (IOException e) {
e.printStackTrace();
}
FirebaseVisionTextRecognizer detector = FirebaseVision.getInstance().getOnDeviceTextRecognizer();
Note that a catch statement that just prints the runtime exception like yours does, should usually be as high as possible in the callstack. So I'd recommend moving it to the code that alls this code, or even higher up. And keep in mind: if you don't catch that error at all, Android will print it too. So consider what you're trying to accomplish with this catch and implement it accordingly.

Related

Malformed PDF print doesn't catch RuntimeException

I try to print a PDF file and it works fine until I try to print a malformed PDF file.
I don't know why the application crashes even though I used try / catch to prevent crashes. I checked and found out that PrintManager.java:1101 throws RuntimeException:
case MSG_ON_KILL: {
if (DEBUG) {
Log.i(LOG_TAG, "onKill()");
}
String reason = (String) message.obj;
throw new RuntimeException(reason);
}
so code below shouldn't lead to crash:
public static void startPdfPrintProcedure(#NonNull Context context, #NonNull String filePath, #Nullable String jobName) {
try {
PrintManager printManager = (PrintManager) context.getSystemService(Context.PRINT_SERVICE);
String jobName = formatDefaultJobName(context.getResources(), jobName);
PrintDocumentAdapter pda = new SimplePrintDocumentAdapter(new File(filePath));
if (printManager != null) {
try {
printManager.print(jobName, pda, null); // <- crash here even though there is a try/catch
} catch (RuntimeException e) {
showUnknownError();
}
} else {
showUnknownError();
}
} catch (RuntimeException e) {
showUnknownError();
}
}
Exception that I get after try to print PDF. :
java.lang.RuntimeException: Cannot print a malformed PDF file
at android.print.PrintManager$PrintDocumentAdapterDelegate$MyHandler.handleMessage(PrintManager.java:1101)
at android.os.Handler.dispatchMessage(Handler.java:112)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7625)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
Why try/catch code doesn't catch this exception? How can I secure this piece of code from crashing?
This happens because some "Genius" Google developer has come up with the "Great" idea of throwing an exception in the main thread causing your application to close.
I have tried to solve the problem using reflection but the implementation is too closed.
Unfortunately, you have to use it assuming the imminent closure of your application in case of incorrect files, unless you want to implement a library to check the PDF format before calling the API.
Google never fails, you always have to mess around with its implementation.
The secondary thread ends up calling this handler.
private final class MyHandler extends Handler {
public static final int MSG_ON_KILL = 5;
...
#Override
public void handleMessage(Message message) {
switch (message.what) {
...
case MSG_ON_KILL: {
if (DEBUG) {
Log.i(LOG_TAG, "onKill()");
}
String reason = (String) message.obj;
throw new RuntimeException(reason);<---------
}
default: {
throw new IllegalArgumentException("Unknown message: "
+ message.what);
}
}
}
}
One way is to check if PDF file is corrupted or not by using PDF viewer library : https://github.com/voghDev/PdfViewPager
import library : implementation 'es.voghdev.pdfviewpager:library:1.1.2'
Use below code to check if PDF file is corrupted
BasePDFPagerAdapter adapter;
PDFViewPager pdfViewPager;
pdfViewPager = findViewById(R.id.pdfViewPager);
adapter = new PDFPagerAdapter(this, path, new PdfErrorHandler() {
#Override
public void onPdfError(Throwable t) {
Log.d("pdfcorrupt",">> yes");
isPDFCorrupted = true;
}
});
pdfViewPager.setAdapter(adapter);
When PDF file is not valid, onPdfError() method will be called.
If your file is corrupted, simply do not allow to print.

Activiti`s RuntimeServiceImpl::startProcessInstanceByKey cannot work well in a concurrent environment

I've got a very strange question in RuntimeServiceImpl::startProcessInstanceByKey.
The code is like this:
#Override
public String startProcessInstanceByKey(String processDefinitionKey, String businessKey,
String authenticatedUserId, Map < String, Object > variables) throws RiskManageException {
log.info("startProcessInstanceByKey,收到开启工作流 processDefinitionKey:{} ,businessKey:{},authenticatedUserId:{},variables:{}", //This can be printed normally
processDefinitionKey, businessKey, authenticatedUserId, JSON.toJSON(variables));
try {
Assert.notNull(authenticatedUserId, "userCode 不能为空");
Assert.notNull(processDefinitionKey, "流程定义key 不能为空");
processCoreService.getIdentityService().setAuthenticatedUserId(authenticatedUserId);
return processCoreService.getRuntimeService()
.startProcessInstanceByKey(processDefinitionKey, businessKey, variables).getProcessInstanceId(); //This statement didn`t execute
} catch (Exception e) {
throw new RiskManageException(ExceptionCodeEnum.START_PROCESS_ERROR, e); //Here throws an exception but the caller didn`t catch any
}
}
The process instance couldn't be created sometimes in a concurrent environment without any exception. It often happens when JDBC connections are about to use up. I want to know more detailed information, what should I do?

Obtaining response from API in Android

I have a problem with obtaining the response from API connection, I used logcat(Log.wtf) testing it then found the logcat in the first class which in my ConnectAPI.java had received the data, but the logcat(Log.wtf) in the second class which in my main.java unable to obtain the response from the first class, please helping me figure it out what the wrong it is, many thanks!
first class(in ConnectAPI.java)
public static void A020 (final Context context, String Manual, final ZooCallback callback){
HttpUrl url = new HttpUrl.Builder()
.scheme(SCHEME)
.host(HOST)
.port(PORT)
.addPathSegments(A020_PATH)
.addQueryParameter("LId", PersonID.getID(context))
.addQueryParameter("Coordinates", getGPS(context))
.addQueryParameter("Manual", Manual)
.build();
Request request = new Request.Builder()
.url(url)
.build();
Log.d("A020 printing out the url", url.toString());
mClient.newCall(request).enqueue(new Callback() {
#Override
public void onResponse(Call call, Response response) throws IOException {
try {
Log.wtf("A020 print out in connectapi",response.toString());
if (response != null && response.isSuccessful()) {
String jsonData = response.body().string();
final JSONObject Jobject = new JSONObject(jsonData);
handler.post(new Runnable() {
#Override
public void run() {
callback.onSuccess(Jobject);
}
});
}
} catch (final JSONException e) {
handler.post(new Runnable() {
#Override
public void run() {
callback.onFail("exception", e.getMessage());
}
});
}
}
#Override
public void onFailure(Call call, final IOException e) {
handler.post(new Runnable() {
#Override
public void run() {
callback.onFail("onFailure", e.getMessage());
}
});
}
});
Second class(in main.java)
ConnectAPI.A020(context, Manual, new ZooCallback(){
#Override
public void onSuccess(JSONArray response){
super.onSuccess(response);
try{
Log.wtf("A020 printing the response in mainjava", response.toString());
}catch(JSONException e){
Log.d("probleminA020", e.getMessage());
}catch(Exception e){
Log.d("probleminA020", e.getMessage());
}
}
public void onFail(String title, String error){
super.onFail(title, error);
Log.d(TAG, error);
}
});
What a Terrible Failure: Report a condition that should never happen. The error will always be logged at level ASSERT with the call stack. Depending on system configuration, a report may be added to the DropBoxManager and/or the process may be terminated immediately with an error dialog.
That is the documentation behind Log.wtf. When you use Log.wtf, there is a chance it throws an error. In which case it is caught by the try-catch you have. Don't use Log.wtf for debug, as this can crash your app.
Use Log.d (or Log.d or whatever you feel like) but not under any circumstance use Log.wtf for debug.
Replace Log.wtf with a different Log call (I recommend Log.d) and try again.
What is most likely happening is that Log.wtf throws an exception. This exception is then caught by the handy try-catch you have there. The code then prints out the error message instead. The reason it isn't printing is because it also throws an exception which you then aren't printing out fully, which explains why you don't know what is causing it
And for future purposes, when printing a stacktrace, use e.printStackTrace as it prints the entire stacktrace and not just the error message.
Another error you are facing is an issue related to your tag length. If oyu target API 24 or above, there is a 23 char limit:
IllegalArgumentException is thrown if the tag.length() > 23 for Nougat (7.0) releases (API <= 23) and prior, there is no tag limit of concern after this API level.
If you don't target API 24 or above, ignore this part.
If you do target API 24 or above, you have to shorten the tag to 23 chars or less. It is generally a good idea to keep the tag short, API 24+ will crash the app if it isn't

Reusing ObjectOutputStreams in Java

I am reusing ObjectOutputStream to send updates between the two clients, this is the server code,
public void run() {
try {
toPlayer1.writeBoolean(true);
toPlayer1.flush();
while (true) {
try {
found = (boolean[][]) fromPlayer1.readObject();
player1Int = fromPlayer1.readInt();
} catch (Exception ex) {
// Handle exception here...
}
if (isWon(player1Int)) {
toPlayer1.writeInt(P1_WON);
toPlayer1.flush();
toPlayer2.writeInt(P1_WON);
toPlayer2.flush();
sendMove(toPlayer2, found, player1Int);
break;
} else {
toPlayer2.writeInt(CONTINUE);
toPlayer2.flush();
sendMove(toPlayer2, found, player1Int);
}
try {
found = (boolean[][]) fromPlayer2.readObject();
player2Int = fromPlayer2.readInt();
} catch (Exception ex) {
// Handle exception here...
}
if (isWon(player2Int)) {
toPlayer1.writeInt(P2_WIN);
toPlayer1.flush();
toPlayer2.writeInt(P2_WIN);
toPlayer2.flush();
sendMove(toPlayer1, found, player2Int);
break;
} else {
toPlayer1.writeInt(CONTINUE);
toPlayer1.flush();
sendMove(toPlayer1, found, player2Int);
}
}
} catch (IOException ex) {
System.err.println(ex);
}
}
private void sendMove(ObjectOutputStream out, boolean[][] found, int score) throws IOException {
try {
out.reset();
out.writeObject(found);
out.writeInt(score);
out.flush();
} catch (Exception ex) {
// Handle exception here...
}
out.writeInt(score);
}
the problem seems to be that some messages are not being delivered correctly, any suggestions? Am I using the flush() correctly? I have added reset(); it is still not working
update, these are the streams:
public void run() {
try {
toPlayer1 = new ObjectOutputStream(player1.getOutputStream());
fromPlayer1 = new ObjectInputStream(player1.getInputStream());
toPlayer2 = new ObjectOutputStream(player2.getOutputStream());
fromPlayer2 = new ObjectInputStream(player2.getInputStream());
regards, c
If you want an object or objects to be sent again, you need to call reset() on the ObjectOutputStream object.
The problem that reset() solves is that when you send an object in a object stream, the protocol attempts to preserve object identity. The first time you send it, the stream sends the object state. Subsequent times, it just sends a marker that says (in effect) "use this object that I sent you previously".
The reset() method says (in effect) to the ObjectOutputStream ... "forget about all objects that I sent previously".
So if you want to send the same object twice, you need to do something like this:
out.writeObject(found);
// change the state of 'found'
out.reset();
out.writeObject(found);
Note that this doesn't affect primitive values sent using their corresponding write methods. Primitive values don't have "identity" and are sent literally each time.
I should also point out that the following is very bad practice.
} catch (Exception ex) {
}
You are silently ignoring all exceptions. This is lazy and dangerous, and you are likely to come to regret it. (Don't do it even in sample code in SO Questions ... 'cos someone might copy your bad code or some Java beginner might emulate your bad habits.)

Java exception handling in non sequential tasks (pattern/good practice)

There are some task that should't be done in parallel, (for example opening a file, reading, writing, and closing, there is an order on that...)
But... Some task are more like a shoping list, I mean they could have a desirable order but it's not a must..example in communication or loading independient drivers etc..
For that kind of tasks,
I would like to know a java best practice or pattern for manage exceptions..
The java simple way is:
getUFO {
try {
loadSoundDriver();
loadUsbDriver();
loadAlienDetectorDriver();
loadKeyboardDriver();
} catch (loadSoundDriverFailed) {
doSomethingA;
} catch (loadUsbDriverFailed) {
doSomethingB;
} catch (loadAlienDetectorDriverFailed) {
doSomethingC;
} catch (loadKeyboardDriverFailed) {
doSomethingD;
}
}
But what about having an exception in one of the actions but wanting to
try with the next ones??
I've thought this approach, but don't seem to be a good use for exceptions
I don't know if it works, doesn't matter, it's really awful!!
getUFO {
Exception ex=null;
try {
try{ loadSoundDriver();
}catch (Exception e) { ex=e; }
try{ loadUsbDriver();
}catch (Exception e) { ex=e; }
try{ loadAlienDetectorDriver();
}catch (Exception e) { ex=e; }
try{ loadKeyboardDriver()
}catch (Exception e) { ex=e; }
if(ex!=null)
{ throw ex;
}
} catch (loadSoundDriverFailed) {
doSomethingA;
} catch (loadUsbDriverFailed) {
doSomethingB;
} catch (loadAlienDetectorDriverFailed) {
doSomethingC;
} catch (loadKeyboardDriverFailed) {
doSomethingD;
}
}
seems not complicated to find a better practice for doing that.. I still didn't
thanks for any advice
Consider the execute around idiom.
Another option (which isn't really all that different, it just decouples them more) is to do each task in a separate thread.
Edit:
Here is the kind of thing I have in mind:
public interface LoadableDriver {
public String getName();
public void loadDriver() throws DriverException;
public void onError(Throwable e);
}
public class DriverLoader {
private Map<String, Exception> errors = new HashMap<String, Exception>();
public void load(LoadableDriver driver) {
try {
driver.loadDriver();
} catch (DriverException e) {
errors.put(driver.getName(), e);
driver.onError(e);
}
}
public Map<String, Exception> getErrors() { return errors; }
}
public class Main {
public void loadDrivers() {
DriverLoader loader = new DriverLoader();
loader.loadDriver(new LoadableDriver(){
public String getName() { return "SoundDriver"; }
public void loadDriver() { loadSoundDriver(); }
public void onError(Throwable e) { doSomethingA(); }
});
//etc. Or in the alternative make a real class that implements the interface for each driver.
Map<String, Exception> errors = loader.getErrors();
//react to any specific drivers that were not loaded and try again.
}
}
Edit: This is what a clean Java version would ultimately look like if you implemented the drivers as classes (which is what the Java OO paradigm would expect here IMHO). The Main.loadDrivers() method would change like this:
public void loadDrivers(LoadableDriver... drivers) {
DriverLoader loader = ...
for(LoadableDriver driver : drivers) {
loader.load(driver);
}
//retry code if you want.
Set<LoadableDriver> failures = loader.getErrors();
if(failures.size() > 0 && tries++ > MAX_TRIES) {
//log retrying and then:
loadDrivers(drivers.toArray(new LoadableDriver[0]));
}
}
Of course I no longer use a map because the objects would be self-sufficient (you could get rid of the getName() method as well, but probably should override toString()), so the errors are just returned in a set to retry. You could make the retry code even simpler if each driver was responsible for knowing how often it should it retry.
Java won't look as nice as a well done C++ template, but that is the Java language design choice - prefer simplicity over complex language features that can make code hard to maintain over time if not done properly.
Try this:
protected void loadDrivers() {
loadSoundDriver();
loadUsbDriver();
loadAlienDetectorDriver();
loadKeyboardDriver();
}
Then:
protected void loadSoundDriver() {
try {
// original code ...
}
catch( Exception e ) {
soundDriverFailed( e );
}
}
protected void soundDriverFailed( Exception e ) {
log( e );
}
This gives subclasses a chance to change the behaviour. For example, a subclass could implement loading each driver in a separate thread. The main class need not care about how the drivers are loaded, nor should any users of the main class.
IMO, for your case, if the exception is "ignorable" it's best if the "loadSoundDriver" method catches the exception and simply returns an error.
Then in the function that loads stuff, you can record all the errors and at the end of the sequence, decide what to do with them.
[edit]
Something like this:
// init
MyError soundErr = loadSoundDriver();
MyError otherErr = loadOtherDriver();
if(soundErr!=null || otherErr !=null){
// handle the error(s)
}
Just surround every single load operation with its own try / catch block.
try {
loadSoundDriver();
} catch (loadSoundDriverFailed) {
doSomethingA;
}
try {
loadUsbDriver();
} catch (loadUsbDriverFailed) {
doSomethingB;
}
// ...
So you can handle every exception by itself and continue processing the oder operations.

Categories

Resources