I've used JNI now and then both in standard Java (desktop) applications and Android applications. Here's the gist of it all:
1 . Your question asks specifically if performance is improved by JNI: mostly, no. There are some very few and specific situations where performance is improved. 98.3% of the time this will not be the case.
Also, adding JNI solely for performance benefits will greatly complicate your project (as compared to just writing it in Java or C/C++):
There are a huge lot of very good tools (IDE, project management tools, libraries, testing tools etc) for Java-only projects (as they are for C and/or C++ -only projects). However there are a lot less (and, IMHO, of lesser quality) such tools that allow to deal with a mixed (Java) + (JNI) +(C and/or C++) project all in one go. More often than not you'll need to bring in separate tools for the Java part of your project, another for the C/C++ part of your project and maybe do a bit of custom tools developement (like scripts and such) for your JNI parts.
Here's an example: I've recently helped a friend with a Java project that had about 90% of its code use the BigDecimal and BigInteger classes. The code did a lot of the common (and some of the more exotic) algebraic operations with these: +-/* but also log, square roots and some I can't remember now. We also tried replacing those parts of the code with JNI and C code that used the MPFR library, after noticing that the features we were using out of Java's BigXXX API were also present in this library. Long story short, in this particular case, the performance gain was of about 10-15 times. Finally we decided to implement the whole module in C and only use Java for the UI along with non-granular JNI calls towards the new C module.
2 . I think the biggest reason why someone would use JNI is if he/she already has a lot of complex C and/or C++ code which needs to be integrated with Java code.
One place where this may apply is when porting an existing video game to the Android platform: Most games are made in C/C++. Android, while at it's core runs on a Linux kernel and deals with C/C++ code, offers in fact a Java API (a Java development environment very similar to the JDK/JVM you get on your PC/Mac). In such a context, doing a thin Java wrapper around existing C++ code in orderto get an old game up and running on Android is a lot faster than converting all the C/C++ code to Java entirely. With the Java thin wrapper approache there is a loss of performance, but it may very well be negligeable, depending on the resource demands of the original game, etc.
Here's a quote from Android's documentation on this:
Before downloading the NDK, you should understand that the NDK will not benefit most apps. As a developer, you need to balance its benefits against its drawbacks. Notably, using native code on Android generally does not result in a noticable performance improvement, but it always increases your app complexity. In general, you should only use the NDK if it is essential to your app—never because you simply prefer to program in C/C++.
(Bad) Example (which illustrates the last point): I've implemented the A* pathfinding algorithim in Java. I've also made a small, simple graphical demonstration of it as an Android application. I then implemented that same algorithm in C. When running separate benchmarks of the Java and C code, C was sometimes 2-3 times faster (especially if there were a lot of GC when running the Java code). So I modified my all-Java Android app to make it use the C code via JNI. While the project got a whole lot more complicated (even when using the excellent Sequoyah Eclipse plugin) the actual performance gain was now more like 10-20%, no where near the 200-300% I was seeing when running the Java and C version of this particular code separately.
How ever (and here I quote from memory) one of the earlier Android books (from the Android version 2 era) gave an advanced example of taking the Quake C++ source code and using JNI to make it into an Android App in like 20 pages (about 2-3 hours of work). If the Quake C++ code was all translated to Java (hundreds of thousants of lines of code) instead, it would take a lot longer than that. And since even the Android devices of that time were able to "hide" the performance penalities that came with JNI calling the Quake game, it made for a good trade-off to use JNI here.