LocationProvider.getInstance() always returns null - java

In my Java ME app, LocationProvider.getInstance(null) always returns me null in emulator.
App in early state, so I didn't tried on real phone.
I believe, I read every article about Location API, but I still don't get, why it's happening to me.
It works fine in different projects, with same settings on same emulator.
Here's the code:
if(currentLp == null)
{
try
{
System.err.println("nope");
currentLp = LocationProvider.getInstance(null);
} catch (LocationException ex)
{
System.err.println("Ooops!");
}
}
CLDC-1.1, MIDP-2.1, Location API 1.0 on DefaultCLDCPhone01 from SDK3.0

CLDC-1.1, MIDP-2.1, Location API 1.0 on DefaultCLDCPhone01 from SDK3.0
LAPI 1.0 - JSR 179. In this version specification, LocationProvider.getInstance returns null "if a LocationProvider that meets the defined criteria can't be returned but there are other supported available or temporarily unavailable providers that do not meet the criteria."
...If it doesn't provide, it will throw exception, according to JSR293
oops JSR293? That's LAPI 2.0 not 1.0. Whatever it specifies, it has nothing to do with your case since as you wrote, it supports earlier version specification. For what to expect in your case, use JSR 179. Or configure DefaultCLDCPhone to support JSR 293 if that's possible (that should be in emulator User Guide)

Related

JDK 8 Optional Features

Am sorry, if am not clear :
I am working on implementing Restful Services using Spring Boot.
I am building a URI based on the request parameters. I am checking for the parameter values and based on that I need to build the URI using the parameter values. If it is NOT null I want to add it to the URI parameter.
host/hello?abc="somevalue"
MultiValueMap<String,String> params=new LinkedMultiValueMap<String,String>();
if (null != abc) {
params.add("abc","123");
}
I am new to JDK 8 features.
1) How can I do this using JDK 8 optional features?
2) Is it possible both to throw an exception and log it using Optional?
I frankly see no point in using an Optional here. The code you have is fine (we can always discuss the Yoda condition).
If you insist, you may write:
Optional.ofNullable(abc).ifPresent(abc -> params.add("abc","123"));
Link: Yoda Conditions: To Yoda or Not to Yoda

NoSuchMethodError on certain OS versions

I’m not sure why I’m getting this error only on certain Android versions (below 5.0).
I’m calling:
myImageView.setImageDrawable(getResources().getDrawable(R.drawable.image, null));
Because of this I’m getting a NoSuchMethodError.
What to do?
Use this
myImageView.setImageDrawable(ContextCompat.getDrawable(this,R.drawable.image));
Instead of this
myImageView.setImageDrawable(getResources().getDrawable(R.drawable.image, null));
EDIT
when you use setImageDrawable(getResources().getDrawable(R.drawable.image, null)); this it will shows below error
NOTE setImageDrawable(getResources().getDrawable(R.drawable.image, null)); this method is added in API level 21
You can read more about ContextCompat
Use ContextCompat, it's helper class for accessing features in
Context.
Using this class you can easily access the following resources,
ImageDrawable
String
Colour
ColorStateList
CodeCacheDir
And many more...
Try by following way,
myImageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.image));
#Prem answer is the right one. Just adding this to provide you with a tip.
In Android documentation there is an indication of which API level included each method. For example, the one you're using was introduced in Android 5.0 (API level 21).
You are calling
getResources().getDrawable(R.drawable.image, null) method which is added in API level 21
check Android docs
If you are using second parameter (theme) as a null
So try to use
getResources().getDrawable(R.drawable.image);
You can use following code for the same
myImageView.setImageDrawable(getResources().getDrawable(R.drawable.image));

Animated Vector Drawable using compat library even on API 22 device

I wrote an animated vector drawable using path morphing (which is available only on API 21 and above). I have a fallback animation using a simple rotation for API below 21. I'm using the animated vector drawable support library (com.android.support:animated-vector-drawable:25.3.1).
Here is how I start the animation:
mBinding.switchIcon.setImageResource(R.drawable.ic_animated_vertical_arrow_down_to_up_32dp);
final Drawable animation = mBinding.switchIcon.getDrawable();
if (animation instanceof Animatable) {
((Animatable) animation).start();
}
This works fine on API 19 and 24, but doesn't work on API 22 nor 23 (I don't have an API 21 device to test).
The API 19 case is logical: the animation is simple, is handled by the support library perfectly, it works. Great.
I expected any API 21 and above devices to pick the built-in vector drawable implementation. However, when debugging, I can see that animation is in fact an instance of AnimatedVectorDrawableCompat: hence, it doesn't support path morphing, and the animation doesn't work.
So why does it work on API 24? Well, animation is an instance of AnimatedVectorDrawable. Hence, path morphing works fine.
So my question is: why doesn't API 21-23 devices pick up the built-in implementation, and rely on the support library, while an API 24 device does pick it up?
As a side note, forcing the device to pick the built-in implementation does obviously works:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AnimatedVectorDrawable drawable = (AnimatedVectorDrawable) getDrawable(R.drawable.ic_animated_vertical_arrow_down_to_up_32dp);
mBinding.switchIcon.setImageDrawable(drawable);
} else {
mBinding.switchIcon.setImageResource(R.drawable.ic_animated_vertical_arrow_down_to_up_32dp);
}
final Drawable animation = mBinding.switchIcon.getDrawable();
if (animation instanceof Animatable) {
((Animatable) animation).start();
}
I also found this (probably) related issue on the Google bug-tracker: https://issuetracker.google.com/issues/37116940
Using a debugger, I can confirm that on API 22 (and probably 23), the support libraries are indeed delegating the work to the SDK's AnimatorSet. I really don't understand the behavior change.
About what follows
These are some notes I thought could be interesting to share, which I took while investigating in the technical explanation of this issue. The intersting, less technical bits are summarized in the accepted answer.
Here is the AVD I'm using, for reference:
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:alpha="1">
<group android:name="group">
<path
android:name="path"
android:pathData="#string/vertical_arrow_up_path"
android:strokeColor="#000000"
android:strokeWidth="2"
android:strokeLineCap="square"/>
</group>
</vector>
</aapt:attr>
<target android:name="path">
<aapt:attr name="android:animation">
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="path"
android:propertyName="pathData"
android:duration="300"
android:valueFrom="#string/vertical_arrow_up_path"
android:valueTo="#string/vertical_arrow_down_path"
android:valueType="pathType"
android:interpolator="#android:anim/accelerate_decelerate_interpolator"/>
</aapt:attr>
</target>
</animated-vector>
And both path resources:
<string name="vertical_arrow_up_path" translatable="false">M 7.41 10 L 12 14.585 L 16.59 10</string>
<string name="vertical_arrow_down_path" translatable="false">M 7.41 14.585 L 12 10 L 16.59 14.585</string>
On an API 22 device, both the built-in and the support version (25.3.1) seems to inflate the same Animator from my AVD above, albeit with a different hierarchy.
With the support version (25.3.1), the AnimatorSet has only one node: an AnimatorSet containing itself a single animation, seemingly matching the ObjectAnimator described in the AVD's XML. Its referent is set to the VectorDrawableCompat, the property name is rightfully pathData, and the values list is containing a single PropertyValuesHolder with two keyframes, matching my start and end paths. Result: doesn't work.
With the build-in version (SDK 22), it's not exactly the same (but the AnimatorSet isn't exactly in the same place, so…): in the AnimatedVectorDrawableState, the mAnimators list has 1 element, which is directly the ObjectAnimator (with the same values as with the support version). Result: works.
The only relevant difference I can see is the ValueAnimator in the PropertyValuesHolder. As it has some reference to the drawable, I guess it may have some typecheck ignoring the support library version of the VectorDrawable class. But that's pure guesswork at that point. I'll keep digging…
I finally got it (and accepted #LewisMcGeary's answer, as I didn't mention in this question that I was looking for the technical bits behind the issue). Here's what happens. As mentioned, on APIs 21-23, the support library is taking over the SDK's implementation, to avoid bugs in said implementations. So we're using AnimatedVectorDrawableCompat and other [whatever]Compat classes. Once the vector itself is loaded, it's the animation's turn.
The animation is delegated to the SDK's ObjectAnimator, whatever the API level we're on (at least on 21+, but I guess it's the same thing on 19 and below). To animate primitive types, the ObjectAnimator has an internal map of functions to call to change the values. However, on complex types, it's relying on a specific method signature which has to be present on the animated object. Here's the method mapping value type to corresponding method to call, from PropertyValuesHolder (SDK, API 22):
private Method getPropertyFunction(Class targetClass, String prefix, Class valueType) {
// TODO: faster implementation...
Method returnVal = null;
String methodName = getMethodName(prefix, mPropertyName);
Class args[] = null;
if (valueType == null) {
try {
returnVal = targetClass.getMethod(methodName, args);
} catch (NoSuchMethodException e) {
// Swallow the error, log it later
}
} else {
args = new Class[1];
Class typeVariants[];
if (valueType.equals(Float.class)) {
typeVariants = FLOAT_VARIANTS;
} else if (valueType.equals(Integer.class)) {
typeVariants = INTEGER_VARIANTS;
} else if (valueType.equals(Double.class)) {
typeVariants = DOUBLE_VARIANTS;
} else {
typeVariants = new Class[1];
typeVariants[0] = valueType;
}
for (Class typeVariant : typeVariants) {
args[0] = typeVariant;
try {
returnVal = targetClass.getMethod(methodName, args);
if (mConverter == null) {
// change the value type to suit
mValueType = typeVariant;
}
return returnVal;
} catch (NoSuchMethodException e) {
// Swallow the error and keep trying other variants
}
}
// If we got here, then no appropriate function was found
}
if (returnVal == null) {
Log.w("PropertyValuesHolder", "Method " +
getMethodName(prefix, mPropertyName) + "() with type " + valueType +
" not found on target class " + targetClass);
}
return returnVal;
}
The interesting part is the for loop trying to match any potential typeVariants to our target class. On this specific case, typeVariants contains only one Class object: android.util.PathParser$PathDataNode. The class we're trying to call a method on (targetClass) is our Compat class: android.support.graphics.drawable.VectorDrawableCompat$VFullPath. And the method we're looking for (methodName) is setPathData.
Sadly, VectorDrawableCompat$VFullPath.setPathData's signature doesn't match: public void android.support.graphics.drawable.VectorDrawableCompat$VPath.setPathData(android.support.graphics.drawable.PathParser$PathDataNode[])
As we only have one item in the typeVariants array, returnVal ends being null, and in the end, the ObjectAnimator has absolutely no way to know how to update the path data of our VectorDrawableCompat.
So from where comes the typeVariants content? The android.util.PathParser$PathDataNode instead of the support one? It's because of the way the animation is inflated. AnimatedVectorDrawableCompat, as we saw, is delegating much of the work to the SDK, which is why some things doesn't work on APIs 19 and below. When reading the target node of its XML, the Animator is inflated by the SDK:
Animator objectAnimator = AnimatorInflater.loadAnimator(mContext, id);
The AnimatorInflater comes from the SDK, and is hence inflating a android.util.PathParser$PathDataNode instead of a android.support.graphics.drawable.PathParser$PathDataNode. I guess the only possible fix for this would be for Google to integrate the AnimatorInflater in the support libraries…
So we're in a hard position here. Google admits that the VectorDrawable implementation from SDKs 21-23 contains bugs (I noticed some drawing issues on API 22 on some SVGs), but we can't use everything from the support library either. So, keep in mind that testing on 19 (or below), 21, 22, 23 and 24 (or above) is just mandatory when it comes to VectorDrawables…
Edit: as of today (09/06/2017), Google released support libraries 25.4, which back-ports path-morphing on API 14+. I guess this issue is now automatically solved (I didn't tested it yet).
AnimatedVectorDrawableCompat does a version check internally and delegates to the system implementation only if the version is API 24 or above (at time of writing).
As for the reasoning, it seems to be as mentioned in the issue you linked to, to avoid problems with the built in implementation for earlier APIs.
For the most recent one, here's the git commit, which refers to this issue in the issue tracker about rendering problems.
Unfortunately that does mean that fixing some things also removes other features (eg. path morphing). I think the type of approach you use in the question is really the only option at present to get around this.

is it possible to block calls to System.exit through ConditionalPermissionAdmin?

The documentation is not helping at all, OSGi in Action does not have an example head to toes on how to do things. For example, I want bundle A to deny a package import from Bundle B, etc. Simple examples, from start to end - I can't find them.
But back to my question, I want to block calls to System.exit for obvious reasons, besides "do not implement your own Security Manager", I did not get much from the Virgo forum, thus my question here.
EDIT
Since I want this to happen in Virgo, here is what I have tried:
public void start(BundleContext context) throws Exception {
System.out.println("===== Starting Bundle PermissionsTest =====");
SecurityManager securityManager = System.getSecurityManager();
if(securityManager == null) throw new IllegalArgumentException("Security Manager is not defined!");
ServiceReference serviceReference =
(ServiceReference) context.getServiceReference(ConditionalPermissionAdmin.class.getName());
if(serviceReference == null) throw new IllegalArgumentException(ConditionalPermissionAdmin.class.getName() + " IS NULL");
else System.out.println("===== Good so far 1 =====");
ConditionalPermissionAdmin conditionalPermissionAdmin =
(ConditionalPermissionAdmin)context.getService(serviceReference);
if(conditionalPermissionAdmin == null) throw new IllegalArgumentException("ConditionalPermissionAdmin can not be found");
else System.out.println("===== Good so far 2 =====");
What I did first in Virgo ie enable the Equinox Security Manager (because this is the one Virgo uses). The specification of the OSGi says that each container has to implement it's own Security Manager extended with a bunch of OSGi specific actions.
In case of Virgo this is Equinox Security Manager. Enabling it is pretty easy - just add two lines in bin/dmk.sh and thus you have it.
Ok, so I do have the ConditionalPermissionAdmin - good! Now, I can for example, add a Security Check, like, BundlePermission say for a Bundle. Sure, but that happens for bundle specific actions, like start/stop/export, etc etc. I can't seem to figure out how to do it for a LifeCycle action - System.exit in my case.
btw, I use version 4.2.0 of the osgi-core, and nope I can't upgrade to 4.3.0, at least not now.
System.exit is governed by RuntimePermission( "exitVm", "<>"), so the example syntax in the spec gives
DENY {
( java.lang.RuntimePermission "exitVm" "*" )
}
In Java code (haven't tested it, so beware):
ConditionalPermissionInfo info = admin.newConditionalPermissionInfo(
"name",
null,
new PermissionInfo[] { new PermissionInfo(
"java.lang.RuntimePermission", "exitVm", "*") },
ConditionalPermissionInfo.DENY
);
ConditionalPermissionUpdate update = admin
.newConditionalPermissionUpdate();
update.getConditionalPermissionInfos().add(0, info);
update.commit();
The subject is rather well treated in the book "OSGi in Action". Please remember that the primary audience of the specification was the implementer of the specification, not the end user. The members were supposed to provide the educational material to bridge that gap. Later specs tried to become more educational for end-users.

Possible to only load specific lines of code according to Android OS version?

Is there a simple line of code that would allow only loading the code if the OS version meets the requirements?
Lets say I have my target OS as 2.2 but the min sdk is 3 for android 1.5 so even if i have some code in my project that isn't compatable with 1.5 it will still compile since the target OS is 2.2. Anyway, I want to ad a feature that requires code that's not in the 1.5 SDK and will cause a crash if it's loaded on a 1.5 phone. Is there a simple thing like this that I can do? So i dont have to make the entire app not available to 1.5 users?
if (Android OS == >2.1){
//Insert code here that requires 2.1 and up}
else{
//insert code that would appear is OS is <2.1}
Yes, you can do that. In fact there is more than one way. (Note: the only Android specific part of this answer is the way that you find out the platform version.)
Suppose that class X has method void y() in version 2.0 onwards, but not before.
One way to invoke this method with out introducing any compile time dependencies whatsoever is to use reflection to locate the Method and call invoke on it. For example:
X x = ...
if (BUILD.VERSION.RELEASE.compareTo("2.0") >= 0) {
// (exception handling omitted ...)
Method m = c.getClass().getDeclaredMethod("y");
m.invoke(x);
}
Another way is to create a version compatibility adapter API for your application like this:
/** Version compatibility adapter API */
interface Compat {
void doY();
}
/** Adapter class for version 1 */
class CompatV1 {
public void y(X x) {
// do nothing
}
}
/** Adapter class for version 2 */
class CompatV2 {
public void y(X x) {
x.y();
}
}
//
// Code to instantiate the relevant adapter for the current platform.
//
Class<?> compatClass;
// (Exception handling omitted)
if (BUILD.VERSION.RELEASE.compareTo("2.0") < 0) {
compatClass = Class.forName("...CompatV1");
} else {
compatClass = Class.forName("...CompatV2");
}
// (Exception handling omitted)
Compat compat = (Compat) compatClass.newInstance();
// The adapter object can be passed around as a parameter, wrapped
// as a singleton or injected using dependency injection.
// Invoke X.y() as follows:
X x = ...
compat.y(x);
The second version looks a bit heavyweight, but it has the advantages that the dynamic (slow, non-type-safe) code is executed just once, and that the version specific code is isolated from the rest of the code. In real life, you would probably put a number of methods into the adapter interface.
This approach requires a bit more thought, to work out how to design the compatibility API so that it cleanly isolates the version dependencies from the rest of the code. You might also to have to revise the adapter API, and create new adapter classes for each new (incompatible) major release.
Finally, if the platform API changes that you need to adapt to entail using classes or methods in the older version that are removed in the newer version, then you will need to compile your various adapter classes (e.g. the CompatV* classes) using different Android SDKs. This will make your build processes rather more complicated.
For other "takes" on this problem, read the following articles on the Android Blog:
Backward compatibility for Android applications
How to have your (Cup-)cake and eat it too.
Here is another example w/o reflection
http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html
See Backward compatibility for Android (using Reflection).
You can check with Build.VERSION.RELEASE, it gives you the current version of your android system (1.5,1.6,2.1,2.2)
There is more on Build.VERSION

Categories