Android - MediaPlayer HTTP Error Handling - java

I am attempting to create an Android app which collects a variety of remote song links and plays them out for users. The app uses Android's MediaPlayer, and every single song link redirects to a Stream URL which the MediaPlayer handles and eventually plays out.
However, some of these song links actually redirect and provide a HTTP 404 Error as they are not available, and I want to know if there is any way to directly handle/catch for these HTTP errors instantly. As of now, what the MediaPlayer does is signal out a:
error (1, -2147483648)
... after it attempts to connect with the data source 10 times, which I can then catch to notify the user that the song is unavailable.
Of course though, having the user wait for 10 retries takes far too much time, and so I want to know if there is a way to catch the very first moment the HTTP error occurs from the MediaPlayer without having to check the URL before sending it to the MediaPlayer, or having to hack away and manage the exceptions with a network proxy connected to the MediaPlayer.
Exception given by MediaPlayer 10 times:
07-16 05:16:30.549: E/MediaHTTPConnection(16698): IOException: java.io.IOException: Http Response: 404

If the error pops up 10 times, and each time an error is put out, then I don't see why a simple try-catch loop will not work:
try {
// download URL
} catch (IOException e) {
// presumably an exception is thrown the first time it gets 404 so put the error handling code here
}
Also, might I suggest using multithreading to download from URLs using something like the ExectutorService which allows you to submit Runnable classes to it and run them concurrently (i.e. the download Tasks for each video so they download at the same time)

Related

JAVA email tracking pixel keep track of reading time

I am working on email tracking pixel project, and I want to make sure that users spend at least 30 seconds reading an email before considering it "read"
I am using Java Springboot for backend server and HTML to create email templates
in my template I put this pixel for tracking:
<img id="tr_pixel" src="https://localhost:8080/api/v1/images/1"/>
once the image is loaded it will request my server:
#GetMapping("/images/{emailID}")
public ResponseEntity<byte[]> getImagePixel (#Pathvariable String emailID) {
try{
// wait 30seconds before saving the event
Thread.sleep(30000);
// If the connection with the client is lost, throw an exception and ignore the next line
//save tracking only if user spend > 30s
service.saveTracking(emailID);
return ok().contentType(IMAGE_PNG).body(pixel);
} catch (ConnectionLostException){
// catch connection lost error if the client close the email before 30s or if did not receive the response
}
}
is there any way to check if the connection with the client is lost, or if the client receives the http response?
Perhaps a 302 redirect will help you.
It will be enough for you to define not one, but two entry points.
The first point #GetMapping("/wait30second/{emailID}"), having received the request, sleeps for 30 seconds and sends a 302 redirect to the second point ...your-site.../images/{emailID}, for example like this: https://www.baeldung.com/spring-redirect-and-forward
The second point #GetMapping("/images/{emailID}") just fixes repeated access to a pixel in
service.saveTracking(emailID) without a pause of 30 seconds. 302 redirect is performed by the client. Therefore, if there is no repeated appeal, it means that the letter was not read.
However, keep in mind that with the massive use of such monitoring, there is a high risk of your emails being flagged as spam.

Best way to handle badly written external exception?

I have an external service I'm calling that just returns 500's with the SAME exception each time no matter the issue.
For example(my api to their service):
Action: Fetch image that does not exist
IMGException: Status code: 500, ErrMsg: File not found
Action: Fetch image that does exist but there are server side issues
IMGException: Status code: 500, ErrMsg: Cannot grab img at this time
Action: Fetch image that does exist but is expired
IMGException: Status code: 500, ErrMsg: Img is expired
What would be the best way to handle this? I was catching them and giving them more descriptive messages to throw to my #ExceptionHandler for logging, etc. Should I just throw them and never catch them since I cannot dependably predict what the exception is caused from and therefore cannot correctly change the status code or message?
You can parse the ErrMsg and throw your own exceptions. But Since the response is from an external service, you can as well include the message from external service in the response to your API in a separate field like ExternalMessage.
This will help the users in case the response from external API changes and you end up throwing a different exception.
I recommend you to simply rethrow these exceptions with the information that the server sends to you and add any information you have. But do not add new information based on what you recieved (with if's, for example), because if they change something your code will just be deprecated.
Of course, never show crypt messages to your final user. In this case add some generic message with instructions about what they can do.

RuntimeException does not halt GAE but returns HTTP 500 when run locally

Let me first provide some background information. If you don't care you can skip to the next paragraph. I wanted to use the DrEdit sample Java application which is integrated with Google Drive as the basis of my application. I need to refactor the code, though, because the original scenario assumed that the user would only access the application through the Drive and never directly. Currently when the latter happens, a RuntimeException is thrown which should not be the case in a normal flow.
Thanks to that issue I stumbled upon a difference between my local environment and the GAE which is manifested when the following code is run:
} catch (CredentialMediator.NoRefreshTokenException e) {
try {
resp.sendRedirect(e.getAuthorizationUrl());
} catch (IOException ioe) {
throw new RuntimeException("Failed to redirect user for authorization");
}
throw new RuntimeException("No refresh token found. Re-authorizing.");
}
When I run this application on GAE, the RuntimeException is thrown (I can see it in the logs) and the sendRedirect is also executed so I get to see the page that should be displayed.
However when I run the same application locally, I get the HTTP 500 error and the RuntimeException is displayed but the sendRedirect is ignored.
So far I haven't been successful in finding an explanation for this behaviour. I would like to know why this is the case and if there are settings that I can change in order to fully replicate the GAE environment locally.
This is how standard defines the sendRedirect(). It actually commits the response so after calling this method you should not be able to change or add to the response. However it does not define what happens if you trigger an exception after redirect.
Anyway, your code is ambiguous on purpose - you should not continue processing the request and throw exceptions after sending redirect. If you have any processing to do, then do it before redirect.
OTOH you should not rely on generic exception handling. Instead install a servlet filter that catches exceptions and return a proper user-readable or device-readable response.

Processing a large file with a web service

I have web service method that is supposed to process a very large file and output several files to the server. However, this web service will just timeout and there will be no way for the invoker to get the CREATED status. I am just wondering whether there is a way to run the processing job (starting a new thread or something) and return the status without waiting for the process to be done.
public Response processFile(InputStream inputStream){
//I want to process the file here
//but I dont want the invoker to wait for that process to finish
//I just want the response to be returned right away
return Response.status(Response.Status.CREATED).build();
}
The file comes from the input stream, right? So if you'll send back a CREATED status (effectually closing the connection) you might sever the connection before you receive the entirety of the input file?
That's what i thought anyways... In which case you'll just want to set the timeout to a lengthier value.
If that's not the case, then i guess it would be fine to start a new thread, process everything there in good time and send back the CREATED status.

Java URLConnection crashes the entire process when I call getInputStream

I am writing a Java applet that downloads images from a web server and displays them to the user. It works fine in Java 1.6.0_3 and later, but on older versions it will completely crash the process about once every 20 page views. There are no error messages in the Java console, because the process is completely frozen. I've waited for almost 15 minutes sometimes, but it never un-freezes.
I added a debug message after every line of code, and determined that the line that is causing the crash is this: InputStream data = urlConn.getInputStream().
urlConn is a URLConnection object that is pointed at the image I want to load. I've tried every combination of options that I can think of, but nothing helps. I haven't been able to find anything in the Java bug database or the release notes for 1.6.0_3.
Has anyone encountered this problem before? Any idea how to fix it?
To determine if it really is the whole JVM process that's frozen, or something else:
(1) get a java stack dump (sigquit/ctrl-break/jstack)
(2) have another background thread doing something you can observe; does it stop?
(3) check if another process (browser/etc) can contact server during freeze? (There's a chance the real problem is server connection depletion)
Is it randomly once-in-every-20-fetches (for example, 5% of the time, sometimes the first fetch in the JVM run), or always after about 20 fetches? If the latter, it sounds like something isn't being closed properly.
If on Linux you can use 'netstat -t' or 'lsof' (with certain options or grepped to show only some lines) to see open sockets; if after each fetch, one more is open, and the count never goes down, you're not closing things properly.
If so, calling close() on the stream you get back and/or disconnect() on the HttpUrlConnection after each try may help. (There may also be more severe limits on the number of connections an applet can leave open, so you're hitting this more quickly than you would in a standalone app.)
The fact that it 'works' in later Javas is also suggestive that some sort of automatic cleanup might be happening more effectively/regularly by finalization/GC. It's best to close things up cleanly yourself but you could also try forcing a GC/runFinalization in the earlier Javas showing the problem.
I'm unsure the cause of the problem you are facing, but I use the following code successfully for synchronously loading images from within applets (loads from either jar file or the server):
public Image loadImage(String imageName) {
// get the image
Image image = getImage(getCodeBase(), imageName);
// wait for it to fully load
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(image, 0);
boolean interrupted = false;
try {
tracker.waitForID(0);
} catch (InterruptedException e) {
interrupted = true;
}
int status = tracker.statusID(thisImageTrackerID, false);
if (status != MediaTracker.COMPLETE) {
throw new RuntimeException("Failed to load " + imageName + ", interrupted:" + interrupted + ", status:" + status);
}
return image;
}

Categories