Android and JDK classes - android

I am builting a library which has android and server versions.
The LdapJDK imports javax.naming classes which are not included in android JDK.
Since LdapJDK wouldn't be called on android version of my library, below code works on android phone.
But I am not sure this is a safe way. If some application(eg: webserver) checks all the classes dependency during initialization, my library would cause exceptions.
I would appreciate any comments.
public static X509Certificate[] getCertFromLDAP(String url, String dn) throws ASN1Exception, CertificateException, UnsupportedEncodingException
{
if (JeTS.getType() == PKIConstants.ANDROID_TYPE)
return LdapAndroid.getCertFromLDAP(url, dn);
else
return LdapJDK.getCertFromLDAP(url, dn);
}

If you want to be safe, create different jars for Android and your server. Exclude anything you don't need/can't use from the Android one.
With that said, as long as you are running on Android 2.x and later, classes are lazy loaded and the code above won't be a problem. Android uses the same pattern to handle backward compatibility, so this is tried and tested.

Related

Android library with dependency not resolving properly

So I have an Android library project, SimpleWidget. I publish it to jcenter.
I can make a new project and add implementation 'my.project:simplewidget:1.2.3' and everything works as expected, I can use SimpleWidget instances and their public APIs.
Now I make another Android library project, ComplexWidget. ComplexWidget is a subclass of SimpleWidget. I add implementation 'my.project:simplewidget:1.2.3' to the build.gradle and everything resolves, and in fact I can even get away without lint yelling for something super basic like ComplexWidget complexWidget = new ComplexWidget().
However, the project will not compile. Any ComplexWidget method that has a return or parameter type of SimpleWidget (e.g., many of the inherited methods, or an interface that accepts SimpleWidget arguments, or a Factory that returns SimpleWidget instances) will not compile and Android Studio complains that "Cannot access my.project.SimpleWidget".
Not sure if I should even mention it for fear of muddying the waters, but if I command click SimpleWidget in, for example, public class ComplexWidget extends SimpleWidget, I get a warning at the top of the file that "Library source does not match the byetcode for the class SimpleWidget".
Any ideas?
TYIA
use api 'my.project:SimpleWidget:1.2.3' instead

Xamarin Realm no realmobject has linker stripped them

I am receiving an exception at runtime as follows.
"No realmobject. Has linker stripped them...."
My solution includes a PCL, Android and IOS project with Visual studio Mac and the realm package 1.6.0 installed in each project. I've also checked that Fodyweaver.xml includes the correct reference and all packages have th same version.
When I have the PCL included in the same folder as the solution (i.e like the default multiplatform solution with PCL) everything works ok.
However I moved the PCL project which includes all the realm logic to a separate folder so I can use it across multiple solutions. My solution now includes the PCL from this external folder and the iOS and Android project also reference the realm packages. the app compiles fine but when I run the application it now receives this exception on the first call to use realm.getinstance.
If Input the PCL project back into the same folder as the main solution as originally created it works fine.
can anyone advise a fix for this ?
I've solved the issue now. Firstly I had applied the solution from #sushhangover, but it didn't work straight off.
After some investigation I discovered the compiler was not weaving the classes and realm objects into the library at all.
I simply loaded the library independently of my main solution, removed and reloaded realm packages and Fody, cleaned it all, rebuild All. and then I could see the fodyweaver working properly. I then added the reference back into my main solution and it all works .
This is the same issue I have when placing my RealmObject models into a separate library (PCL or NetStd) as I use a Viper architecture and I share the same model across multiple solutions.
When Realms.Realm.GetInstance(....) is called the Realm initialization assumes the RealmObjects will be in the same assembly or that the assembly containing is already loaded, but they are not in this case. You can tell this is the case as a compiler warning is issued in the assembly build (via the Fody processing) that is calling GetInstance but that does not have any RealmObjects in it:
Warning: Fody/RealmWeaver: Default schema appears to be empty. This is not an error if you don't have any RealmObject inheritors declared. Otherwise it may be a bug with the weaver. (GeneticCancerSelectors)
So I add a static class to my Realm model library:
public static class RealmModel
{
public static Realms.Realm GetInstance() => GetInstance("");
public static Realms.Realm GetInstance(string databasePath) => GetInstance(new RealmConfiguration(databasePath));
public static Realms.Realm GetInstance(RealmConfigurationBase config = null) => Realms.Realm.GetInstance(config);
public static Task<Realms.Realm> GetInstanceAsync(RealmConfigurationBase config) => Realms.Realm.GetInstanceAsync(config);
}
Now when you need to get a Realm instance, do not call:
Realms.Realm.GetInstance()
But call the one in your Model assembly:
RealmModel.GetInstance()
Thanks to Chris Baxter.
That's my situation.
[WPF Application, Fody 3.0.3, Realm 3.4.0]
Exception: No RealmObjects. Has linker stripped them?
...This is my First Time using Realm, and It's really bad feeling...
A [Brand New] Blank WPF Project
Nuget => Realm
Required FodyWeavers.xml file Created in Solution Folder, because Nuget can't
do this for you now.
(Somehow I Update Then Downgrade a latest version of Fody, after
recongized that Realm don't support Any Fody which version newer
than 3.X)
Awful Exception Occurs, ooooops!
(hours work with System
Auth, SpecialFolder, etc... Until I Discovered Chris Baxter's
answer)
Xml file content:
<?xml version="1.0" encoding="utf-8" ?>
<Weavers>
<RealmWeaver/>
</Weavers>
How to Solve the Problem:
Just Clean And ReBuild Solution, Problem Solved.

Google Cast & Android

I'm attempting to get familiar with Google Cast and it's usage inside an Android application. The codebase I am working with has a working integration, but seems to have various discrepancies when compared to the official guides.
For example, one of the first steps in the guide is to implement the OptionsProvider interface, like so:
class CastOptionsProvider implements OptionsProvider {
#Override
public CastOptions getCastOptions(Context appContext) {
CastOptions castOptions = new CastOptions.Builder()
.setReceiverApplicationId(context.getString(R.string.app_id))
.build();
return castOptions;
}
#Override
public List<SessionProvider> getAdditionalSessionProviders(Context context) {
return null;
}
}
However, the codebase i'm working with does not implement this interface anywhere in the application. Confused, I took a look at the dependencies and noticed the following dependency:
compile 'com.google.android.gms:play-services-cast:$androidGoogleServicesVersion'
This was odd, as the guide recommends using the following instead:
compile 'com.google.android.gms:play-services-cast-framework:10.0.1'
Googling the differences between the com.google.android.gms:play-services-cast-framework library and the com.google.android.gms:play-services-cast library returned no usable results.
Additionally, I was unable to find these libraries on either jcenter or maven.
My questions:
What are the differences between com.google.android.gms:play-services-cast-framework and com.google.android.gms:play-services-cast?
Where are these libraries hosted?
Thanks!
So there is a lot to unpack here...
1.
It sounds like your app is using CCL, which is a modified version of the v2 client. You can verify this by searching your app's build.gradle for the "com.google.android.libraries.cast.companionlibrary:ccl" dependency. This requires com.google.android.gms:play-services-cast rather than com.google.android.gms:play-services-cast-framework, although play-services-cast is a transitive dependency of play-services-cast-framework, so it will be included implicitly. CastOptionsProvider is a new thing for the v3 cast api. ($androidGoogleServicesVersion is a groovy variable that is providing the version number and should be set somewhere else, like in your projects top level build file. This represents the 10.0.1.)
CCL
https://github.com/googlecast/CastCompanionLibrary-android
CCL -> v3 Migration
https://developers.google.com/cast/v2/ccl_migrate_sender
2.
These libraries are either pulled from your local SDK. In the SDK tool it is under SDK Tools/Google Play services. Now it can be pulled from Google's maven repo, which can be setup via the instructions here: https://developer.android.com/studio/build/dependencies.html#google-maven. As a note, in AndroidStudio 3.0 you can simply use google() to load it.

aspectj with android, aspect never called

In the project I'm working we've recently added some level of security, now i don't want to have to rewrite the entire nework logic if it can be done much more easily with AOP.
So, I'm trying to intercept the "onRequestSuccess" method of the requestListeners that are used throughout the application.
For this I have made a simple aspect:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
#Aspect
public class NetworkResponseAspect {
#Around("execution(public void *.onRequestSuccess(..))")
public void intercept(ProceedingJoinPoint joinPoint){
System.out.println("call intercepted " + joinPoint);
try {
joinPoint.proceed();
} catch (Throwable e) {
System.out.println("wut");
}
}
}
I've added the aspectj weaver dependency: compile 'org.aspectj:aspectjweaver:1.8.6'
And it seems to work, at least the annotations are recognized by android studio.
I've placed a breakpoint on the "joinpoint.proceed()" call and started the application in debug mode.
But when I log in (an action that triggers one such listener) nothing happens. Am I missing something?
In Maven you would use AspectJ Maven Plugin (current version is 1.7), in Gradle something similar. This is what you need for compilation if you want to use CTW (compile-time weaving). Those plugins should already contain a dependency on aspectjtools.jar which contains the AspectJ compiler and other stuff. If you use CTW, you need aspectjrt.jar (AspectJ runtime) as a default-scoped (compile) or dependency because it is needed during runtime as well.
If you want to use load-time weaving (LTW), though, you need aspectjweaver.jar on your JVM command line via -javaagent:... because the weaving agent needs to hook into class-loading before your first application class is loaded. P.S.: The weaving agent also contains the AspectJ runtime classes, so you do not need an additional dependency on the runtime in this case.

log4j support in Android

I am attempting to shoehorn an existing SDK onto an android device and one of the dependencies of said SDK is Apache log4j. I am able to load my test program onto the android emulator but when the log4j object "PropertySetter" is called the program fails with a verification exception. Is there a way to ameliorate this issue?
Actually using slf4j turned out a remarkably painless process for me, and it seems the common case, at least for libraries that use straightforward log4j features. You don't really need to swap slf4j in for log4j, only add two slf4j libraries to your project from http://www.slf4j.org/download.html:
-- the slf4j library for Android (currently slf4j-android-1.6.1-RC1.jar)
-- the log4j over slf4j (http://www.slf4j.org/legacy.html#log4j-over-slf4j) bridge.
The latter defines the core log4j classes used by typical implementations and bind them to the slf4j Android implementation. Once the libraries are added the code works.
I successfully got log4j working on android with a Socket Appender and Log4j Chainsaw. All code is located in this repository. Slf4j set up and working too. Be aware you have to configure it programmatically. You cannot use .properties or .xml files the parser wont work on android. Enjoy.
https://sourceforge.net/projects/log4j-android/
There is a new project, which enables log4j on android. Also using log4j over slf4j is possible. It also provides an appender for LogCat. See Logging in Android using Log4J.
The following example shows how to configure and use log4j in Android.
Configure the log4j system in Android
import org.apache.log4j.Level;
import android.os.Environment;
import de.mindpipe.android.logging.log4j.LogConfigurator;
/**
* Simply place a class like this in your Android applications classpath.
*/
public class ConfigureLog4J {
static {
final LogConfigurator logConfigurator = new LogConfigurator();
logConfigurator.setFileName(Environment.getExternalStorageDirectory() + "myapp.log");
logConfigurator.setRootLevel(Level.DEBUG);
// Set log level of a specific logger
logConfigurator.setLevel("org.apache", Level.ERROR);
logConfigurator.configure();
}
}
Logging in Android using log4j using slf4j API
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ExampleLog4JOverSLF4J {
private final Logger log = LoggerFactory.getLogger(ExampleLog4JOverSLF4J.class);
public void myMethod() {
log.info("This message should be seen in log file and logcat");
}
}
Logging in Android using log4j API
import org.apache.log4j.Logger;
public class ExampleLog4J {
private final Logger log = Logger.getLogger(LogConfiguratorTest.class);
public void myMethod() {
log.info("This message should be seen in log file and logcat");
}
}
I would recommend trying to swap in slf4j in place of log4j. It's not a painless switch but its likely to be easier than what you have. slf4j provides a common front-end for several loggers including log4j and there is an slf4j-android package.
No, Android's logging mechanism is not decent. It's very inadequate compared to what log4j can do for you.
The parser for log4j configuration files is not android safe.slf4j's android compatibility thing with log4j just overrides the log4j classes you will use and forces them to use android logcat style logging. You still don't get the full flexibility of log4j on android. I ported log4j on android in my project https://sourceforge.net/projects/log4j-android/ all you have to do is add the two jars in the binaries directory to you classpath. Then
static {
org.apache.log4j.Logger root = org.apache.log4j.Logger.getRootLogger();
final SocketAppender appender = new SocketAppender("192.168.1.4", 4445);
root.addAppender(appender);
}
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(MyClass.class);
static {
logger.info("Hello logger");
}
This will start sending out messages to the remote host you specified. You can then see this messages with Chainsaw http://logging.apache.org/log4j/docs/webstart/chainsaw/chainsawWebStart.jnlp. To make chainsaw work click the second check box on the dialog that pops up hit ok, start your app and a new tab should appear. Be aware your firewall might block it...
Check out this project for a complete implementation: http://code.google.com/p/log4j-android/

Categories

Resources