I am working with a library as a JAR where i have added strings and sending the context of main Application to fetch string to register GCM.
This is my method in the JAR file:-
void registerGCM(Context context){
GCMLibrary.register(context, context.getString(R.string.c2dm_sender));
}
I have declared c2dm_sender in library and in my Application in Strings.
But i am getting this error:
android.content.res.Resources$NotFoundException
I have seen this Using R resources from an android jar file as a reference but not getting it resolved.
I am looking for the solution that R file of my Application is used and c2dm_sender to be used from there.
you can try this code for that......
context.getResources().getString(R.string.c2dm_sender);
Related
I have decompiled an android signed apk and it has a .so file...
when i am copy paste that .so file in my project's jniLibs/(abi)/*.so
The library load successfully, but it gives following error,
java.lang.UnsatisfiedLinkError: Native method not found: com.***.***.****.****.Decode:([BI[B)I
Here decode is native mathod.In singed apk also the are using same signature for native method...and i am also using the same method signature, then also i am getting the error like this...
please help me
thanks in advance
Let your method com.***.***.****.****.Decode be the com.aaa.bbb.ccc.Ddd.Decode. Then you should create package com.aaa.bbb.ccc, create Ddd Java class in this package, define native method
public native int Decode(byte[] in, int length, byte[] out);
in this class and add a static *.so library by means of:
static {
System.loadLibrary("Ddd");
}
to this class. Make sure if your *.so file has name libDdd.so than you have to write just a Ddd in System.loadLibrary.
I had created one project using native c++ support. In this project I am passing int value from activity to c++ code and native code returns whether this is prime number or not. This works perfectly, Now I want to create .so file to use in another project. I had google many post but not got answer how to get different .so file for all devices. So I had rename .apk file to .zip and extract it. After that I got one .so file.
Now I want to use this .so file in another project. therefore I had created new project with different name but package name is same. I had created one directory inside src/main and named it as jniLib in this lib I had copied my .so file directory. In my MainActivity I load so file as static {
System.loadLibrary("native-lib");
}
and call my native method private native String isPrimeNumber(int number);. Here everything is perfect. Now I can get result without having actual c++ code.
Now Again I created new project and follow above steps which was followed by creating second project, but difference is that now I had changed package name of my application. when I run application my application got crashed with error as
FATAL EXCEPTION: main
Process: com.app.androidkt.differentpackage, PID: 16970
java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String com.app.androidkt.differentpackage.MainActivity.isPrimeNumber(int) (tried Java_com_app_androidkt_differentpackage_MainActivity_isPrimeNumber and Java_com_app_androidkt_differentpackage_MainActivity_isPrimeNumber__I)
at com.app.androidkt.differentpackage.MainActivity.isPrimeNumber(Native Method)
at com.app.androidkt.differentpackage.MainActivity.access$000(MainActivity.java:10)
at com.app.androidkt.differentpackage.MainActivity$1.onClick(MainActivity.java:38)
at android.view.View.performClick(View.java:5268)
at android.view.View$PerformClick.run(View.java:21550)
at android.os.Handler.handleCallback(Handler.java:822)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5811)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:681)
So my question are - 1) Is it necessary to use same package name to use .so file in our application as that of .so file.
2) How I can get different .so file directory - currently for time being I had extracted it from apk.
3) To use of .so file is to hide the native code only or there is any other purpose also there?
Thanks in advance.
Your application package name may be anything, but the Java class that consumes native methods implemented in libnative-lib.so must be exactly the same as intended by the authors of this libnative-lib.so file.
The easiest workaround for your setup is to move your com.app.androidkt.differentpackage.MainActivity class to the com.app.androidkt.samplendk package. Android Studio will help you with this refactoring. Note that now you must declare the full path for MainActivity in your AndroidManifest.xml.
Alternatively, you can create a small com.app.androidkt.samplendk.MainActivity
class:
package com.app.androidkt.oldpackage;
public class MainActivity {
static {
System.loadLibrary("native-lib");
}
public native String isPrimeNumber(int number);
}
and add few lines to your MainActivity.java:
package com.app.androidkt.differentpackage;
public class MainActivity extends AppCompatActivity {
private com.app.androidkt.oldpackage.MainActivity pmSolver;
private String isPrimeNumber(int number) {
return pmSolver.isPrimeNumber(number);
}
…
}
If you don't know the exact package name used for this libnative-lib.so, you can find it by parsing its ELF headers: you will see an exported function named similar to Java_com_app_androidkt_ samplendk_MainActivity_isPrimeNumber.
Nitpicker's corner: it is possible to build a JNI library that will hide its designated class name(s), but it is hard to reliably prevent reverse engineering these names; it is also possible to build a JNI library that will seamlessly connect to different packages.
1) Is it necessary to use same package name to use .so file in our
application as that of .so file
No, you can use any package name you desire
2) How I can get different .so file directory - currently for time
being I had extracted it from apk
Copy all .so files to your new project folder: src/main/jniLibs/armeabi
3) To use of .so file is to hide the native code only or there is any
other purpose also there?
.so file is a library. Hence the purpose is to be convenient in reusing implemented features in multiple projects.
I'm trying to load dynamically external classes using DexClassLoader, like #Shlublu proposes here
When I execute my application and the DexClassLoader object try to find the class, it throws a ClassNotFound exception. I have added read and write permissions in the manifest.xml, so it is not the mistake.
I think the problem is the method that I use to make the .jar that I want to load on my application. So I have some questions...
What is the correct method to convert a .java file to .jar using dx
tool?
It is necessary that the package where the external class is loaded be the same that the package of my .jar file? (I think no)
I'm using an Android emulator API 19 (kit-kat)
Since APK is the standard Android package, my suggestion is that you use an APK instead of a JAR. Build an application APK linking the needed JAR (let the Android build tools "dex" the JAR) but without any activity, then install the APK as if it was a normal app. You can then access the APK file itself using the PackageManager to get its path and load it using DexClassLoader.
public static ClassLoader loadAPK(final Context context, final String appName) throws PackageManager.NameNotFoundException {
final String apkPath = context.getPackageManager().getApplicationInfo(appName, 0).sourceDir;
final File tmpDir = context.getDir("tmp", 0);
return new DexClassLoader(apkPath, tmpDir.getAbsolutePath(), null, context.getClassLoader());
}
How can I access a text file in my directory 'src/test/resources'
I can't seem to get it to pickup during my JUnit test
mobile/build.gradle:
sourceSets {
test {
java {
srcDirs = [ 'src/test/java' ]
}
resources {
srcDirs = [ 'src/test/resources' ]
}
}
}
Test method:
#Test
public void test_file() {
URL resource = getClass().getResource("file_four_lines.txt");
File file = new File(resource.getFile()); // Get NullPointerException here
...
}
Prefix the file path with /.
Basically, you'd do something like this:
File helloBleprintJson = new File(
getClass().getResource("/helloBlueprint.json").getPath());
Above snippet is taken from here.
I think this link will help. In your case why not hard code strings for testing? Why not use String.xml instead of "file_four_lines.txt". Internationalization requires a directory structure for each resource file having different language, screen size, orientation, flavor, night/day vision version. For this reason resources are compiled and accessed from the R file. You are trying to bypass this convention by using .txt instead of .xml and accessing the resource directly, it just feels wrong. I don't think testing is you problem as much as not following convention.
Forgive me for posting twice, I do have an answer from the official documentation" Arbitrary files to save in their raw form. To open these resources with a raw InputStream, call Resources.openRawResource() with the resource ID, which is R.raw.filename.
However, if you need access to original file names and file hierarchy, you might consider saving some resources in the assets/ directory (instead of res/raw/). Files in assets/ are not given a resource ID, so you can read them only using AssetManager." Json and txt are non-standard(unsupported) so you have to provide your own implementation/parcer to read this type file. Thanks for this post. I knew something about resources but thanks to your prodding now I know even more. To recap The Android resource system keeps track of all non-code assets associated with an application. The Android SDK tools compile your application's resources into the application binary at build time. To use a resource, you must install it correctly in the source tree (inside your project's res/ directory) and build your application. As part of the build process, the SDK tools generate symbols for each resource, which you can use in your application code to access the resources and of course the symbols referred to are in the generated R file
I'm developing an android library project that should read from an xml file in its raw resources (let's call it xml_file_name.myextension).
What I do is basically creating a jar file of the library project including these folders:
src
gen
lib
res/raw
and referencing it as a library in a test app. This is the code that I use (inside the library project) in order to get the xml file:
int xml_res_id = -1;
for (Field f : R.raw.class.getFields()) {
System.out.println("Raw resource found: " + f.getName());
if (f.getName().equalsIgnoreCase("xml_file_name"))
xml_res_id = f.getInt(null);
}
if(xml_res_id != -1){
System.out.println("xml_file_id: " + xml_res_id);
InputStream is = context.getResources().openRawResource(xml_res_id);
// Decode xml file with SAXParser..
}
(I have the app context because the app explicitly passes it to the library project.)
What happens is that when I launch the test app (and call the method that reads the xml file) I get this error:
It seems that the xml file is actually in the right folder, because:
1) The for loop actually prints "Raw resource found: xml_file_name.myextension" and "xml_file_id: 2130968576"
2) If I put a file named "xml_file_name.myextension" in the res/raw folder of the app, it does not compile, and the error is: "Error generating final archive: Found duplicate file for APK: res/raw/xml_file_name.myextension". This basically gives me the proof that the
file is correctly "imported" from the library project.
Please Note:
I also tried in this other way
InputStream is = context.getResources().openRawResource(R.raw.xml_file_name);
getting the same error.
I honestly don't understand what could be the problem.. what am I doing wrong?
Edit:
for anyone interested in this issue:
I finally realized that this is not possible, basically because when I try to get a resource through context.anymethod I refer to the R file of the app, so I can't give the resource ID got from the R file of my library project.
It will compile, because the library project jar file contains the resource (R.raw.xml_file), but the call to context.something will always give null as a result because it refers to the app R file, that does not have that particular resource in it.
I finally had to put my xml file in the res/raw folder of the app, and access the xml_file raw resource in this way:
int xml_id = context.getResources().getIdentifier("xml_file_name", "raw", context.getPackageName());
// Getting input stream from xml file
InputStream is = context.getResources().openRawResource(xml_id);
I have actually done this with success - the library object should be within the app context. However, it only works with Activity and no other type that I have found. Using the same library with a FragmentActivity fails with NoClassDefFoundError.
EDIT****
It may work with a FragmentActivity within the same root namespace as the library. I was accessing from a different root namespace.
END EDIT****
I have a library project that references an xml file:
InputStream is = context.getResources().openRawResource(R.raw.application_table_defs);
when I call the library method that executes the previous line I have to pass in a context:
Context context = this.getContext();
The key is fully qualifying the getResource to context.getResources()... that was injected.