I'm trying to extract information from my manifest file to display in one of the methods in my jar
file, but seem to be having some issues. Any help is appreciated.
Manifest file:
Manifest-Version: 1.0
Created-By: 1.8.0_60 (Oracle Corporation)
Main-Class: com.example.package1.myClass
Name: com/example/package1
Specification-Title: MyPackage
Specification-Version: v1.1
Specification-Vendor: MyCompanyName
Implementation-Title: MP
Implementation-Version: 2015-11-05-C
Implementation-Vendor: MyName
Name: com/example/package2
Specification-Title: MySecondaryPackage
Specification-Version: v2.0
Specification-Vendor: MyCompanyName
Implementation-Title: M2ndP
Implementation-Version: 2015-11-05-C
Implementation-Vendor: MyName
myClass.java:
package com.example.package1;
import com.example.package2;
class myClass {
public static void main(String[] args) {
try {
myClass clz = new myClass();
Thread.sleep(10000); //pause 10 seconnds so we can see what's spit out
} catch (Exception e) {
//excluded in example
}
}
public myClass() {
Package pkg = getClass().getPackage();
if (pkg == null)
System.out.println("No Package Found");
else {
System.out.println("specs: " + pkg.getSpecificationTitle() + " - " + pkg.getSpecificationVersion());
System.out.println("imps: " + pkg.getImplementationTitle() + " - " + pkg.getImplementationVersion());
System.out.println("name: " + pkg.getName());
}
//other code here excluded from example
}
}
Output:
specs: null - null
imps: null - null
name: com.example.package1
So what gives? It looks like the pkg object is being defined correctly, but it doesn't read any of the Specification or Implementation properties.
<meta-data>A name-value pair for an item of additional, arbitrary data that can be supplied to the parent component. A component element can contain any number of <meta-data> subelements. The values from all of them are collected in a single Bundle object and made available to the component as the PackageItemInfo.
Just open your APK and in treeview select "AndroidManifest. xml". It will be readable just like that.
The manifest file describes essential information about your app to the Android build tools, the Android operating system, and Google Play.
App Manifest With your app open in Android Studio and Project selected on the left, you'll find the Manifest in the manifests top level folder. Double-click AndroidManifest. xml to open it.
So I finally figured it out and thought I'd share incase anyone else was banging their head against the proverbial brick wall as much as I was. I never could get the methods in the Package
class to return anything other than null
. See revised code below for how I managed to pull it off.
package com.example.package1;
import java.util.*;
import java.util.jar.*;
import java.net.*;
class myClass {
public static void main(String[] args) {
try {
new myClass();
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
System.out.println("Done");
try{Thread.sleep(40000);}catch(Exception ee){}
}
}
public myClass() throws Exception {
String clz = getClass().getSimpleName() + ".class";
String pth = getClass().getResource(clz).toString();
String mnf = pth.substring(0, pth.lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF";
String pkg = getClass().getPackage().getName().replaceAll("\\.","/");
URL url = new URL(mnf);
Manifest manifest = new Manifest(url.openStream());
Attributes attr = manifest.getAttributes(pkg);
String value = attr.getValue("Specification-Title") + " - " +
attr.getValue("Implementation-Title") + " " +
attr.getValue("Specification-Version") + " build # " +
attr.getValue("Implementation-Version");
System.out.println(value);
}
}
Output:
MyPackage - MP v1.1 build # 2015-11-05-C
Done
Which is a lot of code to extract four pieces of Metadata.
So if you like a few less lines here's what I used instead:
public myClass() throws Exception {
Attributes attr = new Manifest(new URL(getClass().getResource(getClass().getSimpleName() + ".class").toString().substring(0, getClass().getResource(getClass().getSimpleName() + ".class").toString().lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF").openStream()).getAttributes(getClass().getPackage().getName().replaceAll("\\.","/"));
String value = attr.getValue("Specification-Title") + " - " + attr.getValue("Implementation-Title") + " " + attr.getValue("Specification-Version") + " build # " + attr.getValue("Implementation-Version");
System.out.println(value);
}
Add a slash to the end of your package paths. I.e. change com/example/package1
to com/example/package1/
. Ask for some class within the package com.example.package1
(we'll call it Foo) and everything should work fine.
Package pkg = com.example.package1.class.getPackage();
String specVer = pkg.getSpecificationVersion();
The trailing slash seems to matter. E.g. here's the manifest from Apache's ant.jar
:
Name: org/apache/tools/ant/
Extension-name: org.apache.tools.ant
Specification-Title: Apache Ant
Specification-Version: 1.9.6
Specification-Vendor: Apache Software Foundation
Implementation-Title: org.apache.tools.ant
Implementation-Version: 1.9.6
Implementation-Vendor: Apache Software Foundation
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With