Why use reflection for HttpResponseCache? - java

In the documentation of HttpResponseCache there is a section:
Working With Earlier Releases
This class was added in Android 4.0 (Ice Cream Sandwich). Use
reflection to enable the response cache without impacting earlier
releases:
try {
File httpCacheDir = new File(context.getCacheDir(), "http");
long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
Class.forName("android.net.http.HttpResponseCache")
.getMethod("install", File.class, long.class)
.invoke(null, httpCacheDir, httpCacheSize);
}
catch (Exception httpResponseCacheNotAvailable) {
}
You can see this call via reflection in a questions here on SO (e.g. here), and examples on the web. I also took over code that contains this exact snippet to set up the cache (including the comment, so its probably just copypasta). However, I don't quite understand why you have to use reflection here.
Normally when I want to use a method added at a certain API level above my defined minSdkVersion, I would use the following pattern:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
// do something here
}
so why isn't this the default pattern for HttpResponseCache. What is the advantage of using reflection? It certainly doesn't add to the readability of my code. Does HttpResponseCache actually work below ICS when using reflection this way?
EDIT: I don't have an old Android device here and my emulator refuses to start at all, so I can't simply test it at the moment. Maybe it just crashes horribly without reflection.

What is the advantage of using reflection?
First, quoting the documentation:
This class was added in Android 4.0 (Ice Cream Sandwich).
By "was added", they mean "was added to the Android SDK", and by "Ice Cream Sandwich", they really mean Android 3.2 (API Level 13) based on the rest of the JavaDocs.
However, the HttpResponseCache class itself has existed in the framework for longer, hopefully since Android 1.0 given their recommendations. However, that class was marked with the #hide annotation, so it could not be used directly by apps until API Level 13.
Your Java version guard block using Build will avoid referencing this class directly on older devices. However, it does not actually configure the cache on older devices, either.
Their approach will work on all versions of Android and will allow you to configure the cache, as the class has existed since the beginning.
It is fairly rare that Google explicitly authorizes the use of reflection to get at hidden classes or methods this way, which is why you don't see it often in official documentation.

Unfortunately your suggestion will not work for older versions. Think about the following. They added method install(File, long) to new version. But the code that calls this method is packaged into other jar.
Now you have old version of jar that contains HttpResponseCache and new version of jar that calls it. If you write there
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
cache.install(file, number);
}
NoSuchMethodError will be thrown even if expression of if is false.
Using reflection is a ugly but useful technique to prevent this.

Related

What's the alternative of "ContactsContract.Contacts.LAST_TIME_CONTACTED"?

What should I use instead of ContactsContract.Contacts.LAST_TIME_CONTACTED? According to documentation, LAST_TIME_CONTACTED variable was deprecated. Even it was written in ContactsContract.class
/** #deprecated */
#Deprecated
String LAST_TIME_CONTACTED = "last_time_contacted";
Since it was deprecated then there must be another alternative. But why there's no alternative? Or why the documentation didn't link any alternative?
This constant was deprecated in API level 29.
Contacts affinity information is no longer supported as of Android version Build.VERSION_CODES.Q. This column always contains 0.
In Android Q or higher version, there's no alternative variable either?
There's no alternative - and it's intentional.
Google no longer wants developers with Contacts permission to be able to get access to data related to communication between the user and their contacts.
If you app is eligible to get the CALL_LOG or SMS permissions you can figure out the last contacted timestamp based on the call log / messaging history.
But these permissions are not allowed in Google Play unless your app is of a very specific use-case documented here.

Uncaught SyntaxError: Unexpected end of input - JavaScript injected code into WebView (loadUrl) doesn't work in Android 7 but it does in Android 4

My Android app features an activity where a script is injected into a WebView after a XHTML page is loaded from disk (not the internet).
The app was originally targeted at API level 12 and compiled to the same SDK level, but I had to update it and new rules made me target API level 26.
I also compiled to various SDK level like 17, 19 because I had to use the #JavascriptInterface annotation on public methods of an object that allows the script to call methods that are in Java code.
What I experience is that the WebView is stuck because an error occurs "Uncaught SyntaxError: Unexpected end of input" (no further information with Chrome remote debugging) and this just happens if I test the app on an Android 7 device, while the app works on a Android 4 device even if its API level is not targeted or compiled to.
I read many answers about syntax errors leading to this kind of error, or commented lines in the code, but it is very strange because the old device has no problems and the app works very well.
I tried many combinations in the gradle file.
Is there any other possibility to consider to have my app working?
Many reasons can lead to errors like that or similar (often the error message is not helpful or meaningful).
First of all, if you can have minimum SDK = API level 19 (KITKAT, Android 4.4) or above, use
webView.evaluateJavascript(String script,new ValueCallback<String>() {
#Override
public void onReceiveValue(String s) {
}
});
instead of
webView.loadUrl("javascript: doSomething();");
Android versions from KITKAT above (4.4) have the Chrome WebView instead of the old Android WebView, and the new one has problems with loadUrl for JavaScript injection, it is more strict in evaluating JavaScript (or it has some bugs), in fact.
With loadUrl (and in general) be careful about:
-Using double quotes instead of single quotes marks for string literals delimiters (but maybe not in some special cases),
example:
ch=""\"; //it is good
ch='"'; // it is bad
-When injecting code into an event listener using double quotes as delimiter in source code lines,
example:
var string="parameter";
element.setAttribute("onclick","doSomething('"+stringVar+"');return false;"); // good
-Using curly brakets after "if" clause, not a single direct statement,
example:
if (i>0) {doSomething(i);} // good
if (i>0) doSomething(i); // bad
-Being careful with regular expressions (some characters can be hurtful for the regular expression itself, the result, and maybe the JavaScript interpreter/compiler).

How to solve obstacles related to API version

I am having a restfull service and there are more than 20 clients thats is using this service.
#Path("/provider")
public class Provider{
#Path("/simpleprovider")
#GET
public String getProvider(){
return "Simple Provider";
}
}
Now i have decided to introduce version in service, i have google alot, read my articles but i am totally confused how should i do? suppose i change URI for new service like #Path("/provider/v1") than how should i provide support for existing clients ? by considering this thing should i have to provide change on every client whenever api new version comes in action ?
After Googling i found that there are 3 ways to provide versioning
URL versioning
custom request header
content type
but could not find any practical example please help me in this regard
http://stackoverflow.com/questions/389169/best-practices-for-api-versioning
http://www.narwhl.com/2015/03/the-ultimate-solution-to-versioning-rest-apis-content-negotiation/
http://restcookbook.com/Basics/versioning/
http://www.troyhunt.com/2014/02/your-api-versioning-is-wrong-which-is.html
http://www.lexicalscope.com/blog/2012/03/12/how-are-rest-apis-versioned/
Any help will be greatly appreciated
Versioning a service can be very tricky and is always a big decision when determining the versioning strategy. Especially if you have people using the service. From my experience here are some things to consider:
Understand and communicate when and if you plan on sun setting versions of your API. The last thing you want to have is a problem where you are having to upkeep 10 different versions of an API.
Understand if a version change is absolutely necessary. A good rule of thumb is if core functionality is changing or if the contract can potentially break someones software that is integrating with your API. Here are some things to consider when determining if you really need to version:
If you are removing fields from a resource.
If you are removing (or updating) a URL (or method).
If an existing endpoint (or method) logic is going to change such that it would require a consumer to re-implement.
Overall, if a change that you make would break someone integrating with your API.
Are you going to require database changes that would not be backwards compatible with your previous version(s)? This is when versioning can get really fun (sarcastically) because now you might have to make your database backwards compatible which, in my experience, can be difficult problem to deal with moving forward.
To answer your question, though, I have found the best way to version to be in the URL. Be very simple and deliberate with your versioning so that it is crystal clear for your integrator. For example:
GET /v1/products/{id} // Version 1
GET /v2/products/{id} // Version 2
** If you decide on URL versioning then my advice is to put do "v" for version and a SINGLE number like 1 or 2. Don't get into versions, sub versions, etc... This will make your API seem like it revs a lot which can cause concern for consumers. Also, keep the version as FAR left of the URL as possible. The idea is that everything to the right of the version is the new versioned resource.
I would AVOID using headers to version your service. You don't want to hide versions from your consumer. Be as transparent and explicit about versioning as you possibly can.
Versioning in the URL allows you to also do some useful routing and things on your web server and proxies as well. You can either version like this in your actual code, for example:
[HttpGet("v1/products")]
public Product GetProduct(string id)
{
return _repository.GetProduct(id);
}
or you can version using your web server by setting up virtual directories (or whatever). Then your code might look something like this instead:
[HttpGet("products")]
public Product GetProduct(string id)
{
return _repository.GetProduct(id);
}
However you decide to version it is very important to think about the pro's and con's of each decision and weigh them because if you are running an API that people are using the bad decisions will catch up to you in a hurry.

Avoid using deprecated vaadin 6 methods in vaadin 7

I am on a Project update from version vaadin 6 to vaadin 7. In the vaadin 7 version is used to a large extent the method getPaintable() from the class ApplicationConnection. Nevertheless it is deprecated in vaadin 7 . After examining the api and the official tutorial I have not detected and understood by what method or combination of methods it is replaced. If I want for example to do:
ComponentConnector paintable = this.client.getPaintable(uidl);
How can I excecute the above statement using excusively vaadin 7 (not deprecated) api?
Update:
The answer certifies my suspect that the method in ApplicationConnection getConnector(java.lang.String connectorId, int connectorType) should be used instead, but it is still missing, what is the int type connectorType and how one gets it. Any suggestion?
Update 2:
The replacement suggested in the answer seems reasonable and it might work but my worry is:
Should we use generally UIDL class in vaadin 7? I have the impression that the method updateFromUIDL(UIDL uidl, ApplicationConnection client)should not be called in vaadin 7. How can we the get uidl.getId() , uidl.getTag(). I reckon also that uidl.getId() should be replaced by the method in AbstractConnector getConnectorId(). Am I right?
Update:
After looking at the implementation of the deprecated getPaintable method, you should be able replace it with
ComponentConnector paintable = (ComponentConnector) getConnector(uidl.getId(),
Integer.parseInt(uidl.getTag()));
But don't forget that this can be only a intermediate step. Vaadin 7 changes the general mechanism for Client-Server interaction of widgets:
The old mechanism with UIDL, paintContent() and changeVariables() is still there for a while to ease migration, but it is recommended to update your components to the new mechanisms, which also tend to result in much cleaner code. Using the old mechanisms requires implementing LegacyComponent.
If you compare the integration diagrams of Vaadin 6 with Vaadin 7, you will see how the general integration mechanism have changed.
Original Answer:
Vaadin dev ticket: Deprecate ApplicationConnection.getPaintable(UIDL)
Description:
Functionality from getPaintable(UIDL) should be moved to getPaintable(String paintableId) and getPaintable(UIDL) should be deprecated
Change Log:
#8439 Deprecated ApplicationConnect.getPaintable(UIDL) and added getConnector(String id, String connectorType) instead

Difference between setBackgroundDrawable() and setBackground()

I just upgraded my Android project's build target to API 17, and I'm now getting warnings about setBackgroundDrawable being deprecated. The answer appears to be to use setBackground, but that's not available in older versions.
Is there any actual advantage to using the new method, or did Google just want to change the name? I don't see any point in complicating my code with platform version checks or reflection if the two work the same.
Is there any actual advantage to using the new method, or did Google just want to change the name?
They seemed to only want to change the name, look at the source code:
public void setBackground(Drawable background) {
//noinspection deprecation
setBackgroundDrawable(background);
}
#Deprecated
public void setBackgroundDrawable(Drawable background) { ... }
All of the work is still done in setBackgroundDrawable(). For now, you can ignore the deprecation warnings but understand that in some future API setBackgroundDrawable() will be removed.
In case you are curious, setBackgroundResource(int resid) simply creates a drawable from the resource ID and calls setBackground() (which again calls setBackgroundDrawable())...

Categories