I am trying to integrate the HockeyApp Android SDK in its latest version 4.1.2 into our Qt Android app. I don't know a lot about Android development or Java in general - nor any Qt or HockeyApp internals.
There is some general official documentation on including third party Android (i.e. Java) libraries into a Qt project; however, it mentions a "Create AndroidManifest.xml button in the Deployment settings" which does not exist in the current Qt Creator 4.2.0 version, so I am unsure as to how outdated this documentation is or what parts possibly still apply.
HockeyApp documentation only covers "typical Android development" using Android Studio and their support is not supportive.
On a side note, integrating the HockeyApp iOS SDK took just a couple of hours and was mostly a matter of writing some Objective C bridge code.
Step 1: Add the SDK to the project
First approach
I tried to follow the above documentation and added the unzipped HockeySDK-Android-4.1.2 folder and a project.properties file with contents
android.library.reference.1=HockeySDK-Android-4.1.2/libs/
to a project folder; I also set ANDROID_PACKAGE_SOURCE_DIR in <my project>.pro to that project folder.
Problem: The androiddeployqt build step issues an error message (wrapped for readability)
Error: <path to build folder>/android-build/HockeySDK-Android-4.1.2/libs
is not a valid project (AndroidManifest.xml not found).
but continues anyway and finally fails with an error message (also wrapped for readability)
BUILD FAILED
/opt/Android/android-sdk-macosx/tools/ant/build.xml:573:
HockeySDK-Android-4.1.2/libs/ resolve to a path
with no project.properties file for project <path to build folder>/android-build
Running androiddeployqt with a --verbose switch adds significantly more output, but zero useful information.
Second approach
The downloaded HockeyApp Android SDK zip archive contains - besides some documentation - a file libs/HockeySDK-4.1.2.aar; from this response and this comment, I gather the AAR format is simply a zip archive that, among others, contains an AndroidManifest.xml file. I unzipped libs/HockeySDK-4.1.2.aar in place, then removed it; now the first error message in the build is gone.
Problem: The build fails with
BUILD FAILED
/opt/Android/android-sdk-macosx/tools/ant/build.xml:597:
The following error occurred while executing this line:
/opt/Android/android-sdk-macosx/tools/ant/build.xml:649:
The following error occurred while executing this line:
/opt/Android/android-sdk-macosx/tools/ant/build.xml:655:
<path to build folder>/android-build/HockeySDK-Android-4.1.2/libs/src does not exist.
Again, adding running --verbose to androiddeployqt adds nothing but noise. Looking into the build.xml locations mentioned doesn't help either.
Update:
I tried simply creating the missing folder from the error message; now the build fails as follows:
-dex:
[dex] input: <path to build folder>/android-build/bin/classes
[dex] input: <path to build folder>/android-build/HockeySDK-Android-4.1.2/libs/bin/classes.jar
[dex] input: <path to build folder>/android-build/libs/QtAndroid-bundled.jar
[dex] input: <path to build folder>/android-build/libs/QtAndroidBearer-bundled.jar
[dex] Pre-Dexing <path to build folder>/android-build/libs/QtAndroid-bundled.jar -> QtAndroid-bundled-a06280f40655c27b25038380a4d7f67c.jar
[dex] Pre-Dexing <path to build folder>/android-build/libs/QtAndroidBearer-bundled.jar -> QtAndroidBearer-bundled-a69fa323dbfa477411ea082423128813.jar
[dex] Converting compiled files and external libraries into <path to build folder>/android-build/bin/classes.dex...
[dx]
[dx] UNEXPECTED TOP-LEVEL EXCEPTION:
[dx] java.io.FileNotFoundException: <path to build folder>/android-build/HockeySDK-Android-4.1.2/libs/bin/classes.jar (No such file or directory)
[dx] at java.util.zip.ZipFile.open(Native Method)
[dx] at java.util.zip.ZipFile.<init>(ZipFile.java:219)
[dx] at java.util.zip.ZipFile.<init>(ZipFile.java:149)
[dx] at java.util.zip.ZipFile.<init>(ZipFile.java:163)
[dx] at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:244)
[dx] at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:166)
[dx] at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144)
[dx] at com.android.dx.command.dexer.Main.processOne(Main.java:677)
[dx] at com.android.dx.command.dexer.Main.processAllFiles(Main.java:574)
[dx] at com.android.dx.command.dexer.Main.runMonoDex(Main.java:311)
[dx] at com.android.dx.command.dexer.Main.run(Main.java:277)
[dx] at com.android.dx.command.dexer.Main.main(Main.java:245)
[dx] at com.android.dx.command.Main.main(Main.java:106)
[dx] 1 error; aborting
BUILD FAILED
/opt/Android/android-sdk-macosx/tools/ant/build.xml:888: The following error occurred while executing this line:
/opt/Android/android-sdk-macosx/tools/ant/build.xml:890: The following error occurred while executing this line:
/opt/Android/android-sdk-macosx/tools/ant/build.xml:902: The following error occurred while executing this line:
/opt/Android/android-sdk-macosx/tools/ant/build.xml:283: null returned: 1
I obviously can not just make up some classes.jar file, but there is one single file with that name in <path to build folder>/android-build/HockeySDK-Android-4.1.2/libs, so I can create the missing bin folder and create a symlink in it to ../classes.jar.
The build now succeeds. Step 1 complete.
Step 2: Use the SDK in the project
Going back to the corresponding HockeyApp documentation, I gather I need to modify some code that looks similar to
public class YourActivity extends Activity
...
There is one single occurrence of such code in the project in <path to build folder>/android-build/src/org/qtproject/qt5/android/bindings/QtActivity.java:
public class QtActivity extends Activity
...
That file is copied there by the androiddeployqt tool (part of the Qt SDK) from its source folder inside the Qt SDK at $QTDIR/src/android/java, i.e. /opt/Qt/Qt_5.7.1/5.7/android_armv7/src/android on my machine.
Looking at the androiddeployqt source code, I see there is no way (e.g. by means of a command line parameter) to change the source folder these .java files are taken from, so it is not possible to provide my own set of files and have androiddeployqt copy that instead. Hence, in order to make this work, I must either extend / fix androiddeployqt functionality (sorry, I won't touch that code - yuck!) or modify the copied files at their source directly - which then obviously affects all projects build with that Qt SDK instance.
As a third approach, I could try patching the Java sources after androiddeployqt copied them to the build folder. Unfortunately, this not only makes the development and build workflow absurdly painful; it is also made entirely impossible by the androiddeployqt "one tool does everything" design fail (see below): There is no point in time in the build process where the Java sources exist in the project and the .apk package has not been built yet. I thought the androiddeployqt --no-build parameter would enable that:
--no-build: Do not build the package, it is useful to just install
a package previously built.
but "building" here refers to building the Qt / Java bridge code, not the actual app, so that parameter turns out to be pretty much useless for the task at hand; the build fails with this message - which by itself are a bug as the .apk file from the message does not exist and thus the Android package build was not successful:
Android package built successfully in 1.011 ms.
-- File: <path to build folder>/android-build//bin/QtApp-release-unsigned.apk
Sure, I could copy the sources elsewhere, patch and copy them manually to their final destination, but I think this is where I draw the line.
Actually, looking at the androiddeployqt source code is where the buck stops. Too much time has already been wasted trying to get dysfunctional tools to work:
I will not comment on how smart it is to write a build tool in C++ in the first place - in a single, ~3000 line main.cpp file
I will not comment on the practice of hardcoding the src/android/java path (and many other paths) in the androiddeployqt sources not once, but multiple times - instead of a const QString that at least prepares appropriate (i.e. external) tool configuration
I will not comment on how smart it is to violate the ~50 year old best practice of one tool, one purpose - and duplicate large amounts of functionality provided by Qt, Android or Java tools, such as building, signing, deploying, installing packages, etc.
However, the fact that this tool has made it past code review into a number of major Qt release is nothing short of frightening - and probably a good indicator that it's time to consider dropping Qt as a technology in general
While I am writing this, the Qt 5.8.0 installation keeps freezing, maxing out one CPU core - and has been doing so for the last ~12 hours. I rest my case.
My questions
has anyone had any success with Qt, Android and HockeyApp ?
does anyone have any hints / pointers / wild guesses as to what is wrong here ?
no further questions; I've seen enough
Step 3: Call SDK Java code from C++
(cancelled due to brickwall in step 2)
Answering my own question:
Using the HockeyApp SDK with Qt on Android is not possible without either patching Qt SDK tool source code or Qt SDK Java template source files.
In fact, from what I gather, it is not possible to use any third party libraries with Qt on Android if they require Java source code modification.
FWIW this is an AndroidManifest.xml I use for an app, no external library dependencies though. You could try adding+modifying this to get the deploy to work?
File structure:
/my-project-dir
├── android
│ ├── AndroidManifest.xml
│ └── res
│ └── drawable-mdpi
│ └── icon.png
├── my-project.pro
AndroidManifest.xml:
<?xml version="1.0"?>
<manifest package="my_package_name" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="my_app_name" android:icon="#drawable/icon">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="my_app_name" android:screenOrientation="unspecified" android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="#array/qt_sources"/>
<meta-data android:name="android.app.repository" android:value="default"/>
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="#array/qt_libs"/>
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="#array/bundled_libs"/>
<!-- Deploy Qt libs as part of package -->
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="#array/bundled_in_lib"/>
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="#array/bundled_in_assets"/>
<!-- Run with local libs -->
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
<!-- Messages maps -->
<meta-data android:value="#string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
<meta-data android:value="#string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
<meta-data android:value="#string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
<!-- Messages maps -->
<!-- Splash screen -->
<!--
<meta-data android:name="android.app.splash_screen_drawable" android:resource="#drawable/logo"/>
-->
<!-- Splash screen -->
</activity>
</application>
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="14"/>
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
Remove the comment if you do not require these default permissions. -->
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
Remove the comment if you do not require these default features. -->
<!-- %%INSERT_FEATURES -->
<!-- %%INSERT_PERMISSIONS -->
</manifest>
Related
I have a Cordova project created using Visual Studio 2015's Tools for Apache Cordova. We're trying to create a plugin that uses an external library, and that library depends on various things such as Google's location services. I've found that they go in a .gradle file, but have no idea how to get them in that file using TACO. I can do it manually, but VS regenerates the .gradle file every time the project's built.
I'm new to TACO, so it may be I'm missing something.
Very common problem when starting out with Cordova Plugins. I've struggled with this in the past. Start by reading this. You need to add some entries to your plugin.xml file. In that file you should have a section for each platform you support. You should also not be modifying the platform/android/build.gradle file directly. Make a separate one which will eventually get it's contents appended to your platform/android/build.gradle using <framework>.
<platform name="android">
</platform>
In platforms add something similar to match your features:
Permissions docs
<config-file target="AndroidManifest.xml" parent="/*">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
....
</config-file>
External Libs docs
<framework src="src/android/build.gradle" custom="true" type="gradleReference" />
<source-file src="lib/android/sample-android-sdk/sample.jar" custom="true" target-dir="lib" />
I am trying to generate multiple apk with same code using ANT and have followed many posts to get it done. But i am unable to build the project successfully.
Let me start with my first problem. I have a main project which has two library projects, something like
Main Project ---> Library Project(isLibrary) ---> Google Play Services (isLibrary)
When i am trying to update those projects, each and every time getting a message like
It seems that there are sub-projects. If you want to update them
please use the --subprojects parameter.
So, from the above message it looks like am failing at early step of the build process.
Then i have added the following snippet prior to
<target
name="-package-resources" >
<!-- only package resources if *not* a library project -->
<echo message="Current Package name: ${app.custompackagename}" />
<do-only-if-not-library elseText="Library project: do not package resources..." >
<aapt
androidjar="${project.target.android.jar}"
apkfolder="${out.absolute.dir}"
assets="${asset.absolute.dir}"
buildType="${build.target}"
command="package"
debug="${build.is.packaging.debug}"
executable="${aapt}"
ignoreAssets="${aapt.ignore.assets}"
libraryPackagesRefid="project.library.packages"
libraryRFileRefid="project.library.bin.r.file.path"
libraryResFolderPathRefid="project.library.res.folder.path"
manifest="${out.manifest.abs.file}"
manifestpackage="${app.custompackagename}"
nocrunch="${build.packaging.nocrunch}"
previousBuildType="${build.last.target}"
resourcefilename="${resource.package.file.name}"
resourcefilter="${aapt.resource.filter}"
versioncode="${version.code}"
versionname="${version.name}" >
<res path="${out.res.absolute.dir}" />
<res path="${resource.absolute.dir}" />
<!-- <nocompress /> forces no compression on any files in assets or res/raw -->
<!-- <nocompress extension="xml" /> forces no compression on specific file extensions in assets and res/raw -->
</aapt>
</do-only-if-not-library>
</target>
then i have executed the following command from command line
ant debug -Dpackage.manifest.name=com.example.test
and here are my logs
BUILD FAILED
D:\Vijay\Android\android-sdk_r06-windows\android-sdk_r06-windows\android-sdk-win
dows\tools\ant\build.xml:571: Failed to resolve library path: D:\Vijay\Android\G
itHub\project\library
I'm working on a PhoneGap/Cordova plugin that's supposed to provide a socket for sending and receiving OSC messages (Open Sound Control). For that purpose I'd like to use JavaOSC but I'm uncertain about how to include the library into my project.
I'm using Android Studio and I've basically followed this tutorial to set up my project. First I placed the raw JavaOSC class-files in the same directory as my OSCPlugin.class and placed the import declarations at the to of my OSCPlugin.class:
import com.illposed.osc;
That didn't work.
As a next step I tried to add the library from maven within the project's module settings. I was able to download the jar files from maven and install put them into /platforms/android/libs. Within the settings for the module 'android' I can see that 'Android API 17' is supposed to be used as SDK, including cordova-3.1.0 and com.illposed.osc:javaosc-core:0.2 - both activated. I can see the cordova-3.1.0.jar as well as javaosc-core-0.2.jar, containing com.illposed.osc in the navigator within Android Studio.
However, when trying to compile my project I get:
Gradle: cannot find symbol class osc
triggered from within OSCPlugin.class that contains the above mentioned import declaration
I have very little experience with Java and even less with Android development. But I'd be interested in solving this riddle and get started. I have searched the Java docs but the problem doesn't merely lie within Java but rather within the structure of the Android project.
I'd be thankful if someone could shed some light on this issue. Any hint's highly appreciated!
For one of my Phonegap projects I needed the Apache Commons Net, trying to follow these steps:
...
<source-file src="src/android/xxx.jar" target-dir="libs" framework="true" />
<source-file src="src/android/MyPlugin.java" target-dir="src/com/mypackage" />
...
unfortunately, without success. The trick was to embed the third-party library in another plugin (following the very plugin structure). Having the org.apache.commons.net as a top level directory:
org.apache.commons.net
+src
+android(this is where the .jar is located)
+www (empty, not referencing any .js)
+plugin.xml
For brevity, plugin.xml as follows:
<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
id="org.apache.commons.net"
version="0.1.0">
<name>org.apache.commons.net</name>
<description>org.apache.commons.net</description>
<license>Apache License, Version 2.0</license>
<keywords>org.apache.commons.net</keywords>
<!-- android -->
<platform name="android">
<config-file target="res/xml/config.xml" parent="/*">
<feature name="org.apache.commons.net">
<param name="android-package" value="org.apache.commons.net"/>
</feature>
</config-file>
<source-file src="src/android/commons-net-2.2.jar" target-dir="libs" framework="true" />
</platform>
</plugin>
Assuming the org.apache.commons.net directory is located in your local git repo, adding it to your project is as trivial as:
phonegap local plugin add /path/to/your/org.apache.commons.net
To add external library, basically all you have to do is copy the jar to the /libs folder.
Here you have a bad import in your source.
import is used to import a class by specifying the package name followed by the class name and here you only specify the class name, so the error "cannot find symbol class osc" you are having is because there is no class osc.
You should use either
import com.illposed.osc.*; if you want to import all classes from the package
or add an import for each class from the package that you are going to use.
And if you want make the plugin installable using the CLI or phonegap build, you also have to update plugin.xml to add the copy of the jar file.
ps in case you don't know, you won't be able to use classes from com.illposed.osc.ui as they are using swing and designed for the jvm and not android.
I'm working on application which make use of the org.simalliance.openmobileapi API to use the Secure element communication.
The application is Native that is the main Activity call a JNI library to operate. The JNI library use the JNI Method to call functions of the org.simalliance.openmobileapi package.
The API level is 8 as write in the mainfest:
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8"/>
The application work fine with Android 2.3.6 but when i try to launch the application from Android 4.0.4 or later the application can't find the SEService class of the org.simalliance.openmobileapi. Useful log are:
09-20 11:00:48.509: I/dalvikvm(1104): Failed resolving Lpkg/wrapper/SecureChannel; interface 203 'Lorg/simalliance/openmobileapi/SEService$CallBack;'
09-20 11:00:48.509: W/dalvikvm(1104): Link of class 'Lpkg/wrapper/SecureChannel;' failed
01-01 22:08:33.460: I/dalvikvm(10881): java.lang.NoClassDefFoundError: org.simalliance.openmobileapi.SEService$1
The class SecureChannel is a Java class that is called by the JNI to operate over the Secure Element and is contained in a jar that is "dexed" at compiling time with the rest of the project.
The package org.simalliance.openmobileapi.jar is contained in the /system/framework folder in both version of Android:
On Android 2.3.6
-rw-r--r-- root root 29148 2012-11-15 11:24 org.simalliance.openmobileapi.jar
On Android 4.0.4
-rw-r--r-- root root 313 2012-06-11 15:49 org.simalliance.openmobileapi.jar
-rw-r--r-- root root 24864 2012-06-11 15:49 org.simalliance.openmobileapi.odex
The only difference i see is the odex file in the Android 4.0.4 OS.
Is there a way to include the classpath or the reference to a package contained in the /system/framework folder ?
I've found a clean solution to this problem.
Instead of saying to the compiler that you want to compile the library into your application, just say that the library is provided for your application and everything will works fine.
In my case I use Gradle with Android studio.
So I just extract the .jar file from the downloaded add-on in my SDK path:
sdk\add-ons\addon-open_mobile_api-giesecke_devrient_gmbh-18\libs
And placed it in my application libs folder.
Then in my build.gradle file I replaced :
dependencies {
compile files('libs/org.simalliance.openmobileapi.jar')
}
with this :
dependencies {
provided files('libs/org.simalliance.openmobileapi.jar')
}
And now everything works just fine.
Here is my configure in Android Studio
in app/build.gradle
dependencies {
compile fileTree(include: ['*.jar'], exclude: ['org.simalliance.openmobileapi.jar'], dir: 'libs')
provided files('libs/org.simalliance.openmobileapi.jar')
}
in AndroidManifest.xml ,turning it true or false depends on you
<uses-library
android:name="org.simalliance.openmobileapi"
android:required="false" />
and in /system/framwork/, "org.simalliance.openmobileapi.jar" is required or an exception will throw up.
I solved the problem putting on src/ folder of my project the source contained in this package:
http://code.google.com/p/seek-for-android/downloads/detail?name=MSC%20Smartcard%20Service%203.0.tar.gz&can=2&q=
More precisely the source in the package com.mobilesecuritycard.openmobileapi.jar which is the new version of the seek-for-android library made to replace the old package org.simalliance.openmobileapi.jar.
I had to rename all the reference to the package from com.mobilesecuritycard to org.simalliance because the SecureChannel class was written with the old package so the old package name must be used.
In android manifest don't forget add:
<application
android:name=....
android:icon="#drawable/icon"
android:label="#string/app_name"
android:allowBackup = "true" >
<!-- support USIM -->
<uses-library
android:name="org.simalliance.openmobileapi"
android:required="false"/>
I'm having trouble getting javadoc to reference another project's API.
There's a strict hirearchy between the projects (a "common" project referenced by an "app" project).
Both projects build just fine, so there's no issue with classes and packages not actually existing.
My understanding is that javadoc doesn't have a sort of buildpath in the same way that Java does, but uses links to other javadoc websites instead. There's some pretty logical reasons for this in terms of being able to generate HTML cross references.
My attempt to make this goes as follows:
I've built the javadoc for the common project
I threw that on a webserver on my intranet
I added a link to the api (on my intranet) to the javadoc ant task in the app project.
I attempted to build the app project
Javadoc still spits out error messages of the form:
[javadoc] C:\Users\couling\workspace\app\src\com\blahblah\app\AppMain.java:14: package com.blahblah.common.foo does not exist
[javadoc] import com.blahblah.common.foo.Bar
[javadoc] ^
The resulting javadoc has no cross links between the projects.
The ant tasks for the two projects are as follows:
Common:
<javadoc
access="protected"
author="true"
classpath="."
destdir="out/doc/docs"
nodeprecated="false"
nodeprecatedlist="false"
noindex="false"
nonavbar="false"
notree="false"
packagenames="*"
source="1.6"
sourcepath="src"
splitindex="true"
use="true"
version="true">
<link href="http://download.oracle.com/javase/6/docs/api/" />
</javadoc>
App:
<javadoc
access="protected"
author="true"
classpath="."
destdir="out/doc/docs"
nodeprecated="false"
nodeprecatedlist="false"
noindex="false"
nonavbar="false"
notree="false"
packagenames="com.blahblah.app.*"
source="1.6"
sourcepath="src"
splitindex="true"
use="true"
version="true">
<link href="http://intranet.blahblah.com/api/common/docs/" />
<link href="http://download.oracle.com/javase/6/docs/api/" />
</javadoc>
Any thoughts on what I need to do to get app to reference common?
The <link> element (or the -link option for command line javadoc) only help with generating the links - but Javadoc stops at an earlier point, it can't really work with your app classes if they reference unknown (common) classes.
In this respect, Javadoc works just like Javac - you must somehow point it to the classes to be used, i.e. they must be in the class path. You can use a <classpath> element to point to the jar file or class directory, or a <sourcepath> element, to point to the sources (do this if you need to inherit some comments from them).
This is not needed for linking to the standard API, since it is already included in the compiler.
Note that linking in this way requires Javadoc to download the package-list from this URL - you can instead point to a local directory which contains this package-list file.