I'd like to understand a bit better the way GPS works in Android and I'd like to include some traces to track it and modify its behavior. In GpsLocationProvider.java I found the methods:
private native boolean native_init();
private native void native_disable();
private native void native_cleanup();
private native boolean native_start(int positionMode, boolean singleFix, int fixInterval);
private native boolean native_stop();
private native void native_set_fix_frequency(int fixFrequency);
private native void native_delete_aiding_data(int flags);
private native void native_wait_for_event();
// returns number of SVs
// mask[0] is ephemeris mask and mask[1] is almanac mask
private native int native_read_sv_status(int[] svs, float[] snrs,
float[] elevations, float[] azimuths, int[] masks);
private native int native_read_nmea(int index, byte[] buffer, int bufferSize);
private native void native_inject_location(double latitude, double longitude, float accuracy);
// XTRA Support
private native void native_inject_time(long time, long timeReference, int uncertainty);
private native boolean native_supports_xtra();
private native boolean native_inject_xtra_data(byte[] data, int length);
// DEBUG Support
private native String native_get_internal_state();
// AGPS Support
private native void native_agps_data_conn_open(String apn);
private native void native_agps_data_conn_closed();
private native void native_agps_data_conn_failed();
private native void native_set_agps_server(int type, String hostname, int port);
// Network-initiated (NI) Support
private native void native_send_ni_response(int notificationId, int userResponse);
However, I would like to see what they do in detail. Where are they implemented? I've found the qualcomm drivers for GPS but I guess that there's a missing layer in between where the hardware issues are abstracted (HAL layer?).
I hope you are aware that these are supposed to be mapped at the JNI layer to corresponding GPS vendor APIs. You are right when you say that these are implemented as part of HAL layer. The HAL layer will be part of GPS chipset Vendor code.
Since you spoke about qualcomm, I can tell you that qualcomm has the HAL layer for sure. You can check their engine part if you have their source. But it has copyrights & hence, I cannot give you the source code which implements the native APIs.
Related
I am working on a radio app . I used exoplayer as player on my project and I want to add audio visualizer on my playeractivity . but I couldn't find any tutorial or sample for it . I just made a customeRenderfactory and add it to my player . But I don't know what should I do more ? any help or suggestion ? I should mention my player work fine right now and I just need to find a solution to add visualizer to it .
RenderFactory class :
public class RenderFactory extends DefaultRenderersFactory {
private TeeAudioProcessor.AudioBufferSink listener;
private AudioProcessor[] aMProcessors;
private TeeAudioProcessor teeAudioProcessor;
private AudioRendererEventListener eventListener;
public RenderFactory(Context context, TeeAudioProcessor.AudioBufferSink myListener) {
super(context);
this.listener = myListener;
teeAudioProcessor = new TeeAudioProcessor(this.listener);
}
#Override
protected void buildAudioRenderers(Context context, int extensionRendererMode, MediaCodecSelector mediaCodecSelector, #Nullable DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys, boolean enableDecoderFallback, AudioProcessor[] audioProcessors, Handler eventHandler, AudioRendererEventListener eventListener, ArrayList<Renderer> out) {
aMProcessors = new AudioProcessor[]{teeAudioProcessor};
super.buildAudioRenderers(context, extensionRendererMode, mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys, enableDecoderFallback, aMProcessors, eventHandler, eventListener, out);
}
}
in my playerActivity I added this code and set renderfactory to my player but nothing happened .
RenderFactory renderFactory = new RenderFactory(this, new TeeAudioProcessor.AudioBufferSink() {
#Override
public void flush(int sampleRateHz, int channelCount, int encoding) {
// what should I add here?
}
#Override
public void handleBuffer(ByteBuffer buffer) {
// what should I add here?
}
});
I tried to followed this tutorial but I wasn't successful.
tutorial
To directly answer your question:
#Override
public void flush(int sampleRateHz, int channelCount, int encoding) {
// you dont have to do anything here
}
#Override
public void handleBuffer(ByteBuffer buffer) {
// This will give you the bytes from the sound that is going to be played
// here you apply FFT so the audio move to the frequency domain instead of time based
}
You can learn more about FFT here
FFT is a well known algorithm, so you may find it implemented on plenty os sites. You can use this library if yout want, but there is standalone codes around.
Once you have the FFT array, you can draw the values in a view.
You can use this guy's code as an example: https://github.com/dzolnai/ExoVisualizer
There's also a blog post he made about it: https://www.egeniq.com/blog/alternative-android-visualizer
I have been implemented this project: https://github.com/yaylas/AndroidFaceRecognizer into Android Studio. I included OpenCV using tutorial: https://www.youtube.com/watch?v=OTw_GIQNbD8 (this is static initialization). Moreover, I set in Android Studio settings proper NDK location.
Problem is that, if I add this Class:
package com.yaylas.sytech.facerecognizer;
import java.util.Vector;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import android.widget.Toast;
public class DetectionBasedTracker
{
public DetectionBasedTracker(String cascadeName, int minFaceSize, boolean isFaceDetector) {
mNativeObj = nativeCreateObject(cascadeName, minFaceSize, isFaceDetector);
}
public long getNativeObj(){
return mNativeObj;
}
public void setMinFaceSize(int size) {
nativeSetFaceSize(mNativeObj, size);
}
public void detect(Mat imageGray, MatOfRect faces) {
nativeDetect(mNativeObj, imageGray.getNativeObjAddr(), faces.getNativeObjAddr());
}
public void release() {
nativeDestroyObject(mNativeObj);
mNativeObj = 0;
}
public static Vector<Mat> imageVector = new Vector<Mat>();
public static void addElement(Mat m){
imageVector.add(m);
System.out.println("--------------------------------- elementAdded: "+imageVector.size());
}
public static long getElementAt(int index){
if(index >= imageVector.size() || index < 0){
return 0;
}
System.out.println("-------------------------***** get element: "+imageVector.size()+" index: "+index);
return imageVector.elementAt(index).getNativeObjAddr();
}
public static int getImageCount(){
return imageVector.size();
}
private long mNativeObj = 0;
private static native long nativeCreateObject(String cascadeName, int minFaceSize, boolean faceDetection);
private static native void nativeDestroyObject(long thiz);
private static native void nativeStart(long thiz);
private static native void nativeStop(long thiz);
private static native void nativeSetFaceSize(long thiz, int size);
private static native void nativeDetect(long thiz, long inputImage, long faces);
}
An error is returned:
Cannot resolve corresponding JNI function
I tried everything, but the error still is there. I would like to ask, where can be a problem?
There are several reasons why the runtime might not be able to resolve the JNI function. Test these hypotheses:
The native code library didn't get bundled into your APK. Look inside the APK for it.
The native code library is in the wrong directory of the APK. Again, look and see.
The Java class got mangled by ProGuard so the names no longer match with the native library. Try turning off ProGuard. It should be off for debug builds.
If your native code library is compiled for ARM but you're running in an x86 based Android emulator (or vice versa), it won't be able to load that library.
Think of more hypotheses, then test them.
The page http://opencv.org/platforms/android.html has lots of info about OpenCV on Android, including links to tutorials.
I have an Android project based upon the fantastic code available at http://ikaruga2.wordpress.com/2011/08/10/video-live-wallpaper-part-4/. Essentially, this app is a live wallpaper that uses FFMpeg to read a video file frame by frame and play it out to screen using GLWallpaperService.
I downloaded the code and was able to get it running successfully on my phone. I made several changes and then tested again on several devices and all worked fine. This evening I tried to change the package name from "ffvideolivewallpaper.frankandrobot.com" to "com.nightscapecreations.orionkeysfree". I did a search and replace in the java, c, and xml files to replace them. I also modified the c file to replace "Java_ffvideolivewallpaper_frankandrobot_com_NativeCalls" with "Java_com_nightscapecreations_orionkeysfree_NativeCalls". However, when I run the app on my phone now I receive this error:
09-30 12:53:44.911: E/AndroidRuntime(24237): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:590)
09-30 12:53:44.911: E/AndroidRuntime(24237): at dalvik.system.NativeStart.main(Native Method)
09-30 12:53:44.911: E/AndroidRuntime(24237): Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1936]: 145 could not load needed library '/data/data/ffvideolivewallpaper.frankandrobot.com/lib/libavutil.so' for 'libavcore.so' (load_library[1091]: Library '/data/data/ffvideolivewallpaper.frankandrobot.com/lib/libavutil.so' not found)
09-30 12:53:44.911: E/AndroidRuntime(24237): at java.lang.Runtime.loadLibrary(Runtime.java:370)
09-30 12:53:44.911: E/AndroidRuntime(24237): at java.lang.System.loadLibrary(System.java:535)
09-30 12:53:44.911: E/AndroidRuntime(24237): at com.nightscapecreations.orionkeysfree.NativeCalls.<clinit>(NativeCalls.java:64)
09-30 12:53:44.911: E/AndroidRuntime(24237): ... 13 more
I'm assuming there's a reference to the old package name that I'm missing somewhere, but I can't find anything with Eclipse's file search. Eclipse is managing the NDK and compiling all the libraries and c code for me. So far I've tried:
Doing a clean build
Restarting Eclipse
Removing everything in the libs directory and building again
The native calls file that is erroring looks like this:
package com.nightscapecreations.orionkeysfree;
public class NativeCalls {
//ffmpeg
public static native void initVideo();
public static native void loadVideo(String fileName); //
public static native void prepareStorageFrame();
public static native void getFrame(); //
public static native void freeConversionStorage();
public static native void closeVideo();//
public static native void freeVideo();//
//opengl
public static native void initPreOpenGL(); //
public static native void initOpenGL(); //
public static native void drawFrame(); //
public static native void closeOpenGL(); //
public static native void closePostOpenGL();//
//wallpaper
public static native void updateVideoPosition();
public static native void setSpanVideo(boolean b);
//getters
public static native int getVideoHeight();
public static native int getVideoWidth();
//setters
public static native void setWallVideoDimensions(int w,int h);
public static native void setWallDimensions(int w,int h);
public static native void setScreenPadding(int w,int h);
public static native void setVideoMargins(int w,int h);
public static native void setDrawDimensions(int drawWidth,int drawHeight);
public static native void setOffsets(int x,int y);
public static native void setSteps(int xs,int ys);
public static native void setScreenDimensions(int w, int h);
public static native void setTextureDimensions(int tx,
int ty );
public static native void setOrientation(boolean b);
public static native void setPreviewMode(boolean b);
public static native void setTonality(int t);
public static native void toggleGetFrame(boolean b);
//fps
public static native void setLoopVideo(boolean b);
static {
System.loadLibrary("avcore");
System.loadLibrary("avformat");
System.loadLibrary("avcodec");
//System.loadLibrary("avdevice");
System.loadLibrary("avfilter");
System.loadLibrary("avutil");
System.loadLibrary("swscale");
System.loadLibrary("video");
}
}
How do I resolve this error? What else needs done when changing the package name? I'll need to do this many times in the future.
EDIT:
It looks like I was looking in the wrong place. The developer of the original version of the code pointed out that there is a package name passed in when compiling the ffmpeg libraries. He was nice enough to compile a new version for me with my package name and the wallpaper worked perfectly. We tried a compile without the package name, but when added to the app it just resulted in:
10-04 08:20:57.414: E/AndroidRuntime(19139): Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1936]: 145 could not load needed library 'libavutil.so' for 'libavcore.so' (load_library[1091]: Library 'libavutil.so' not found)
I'm guessing that I'll just need to compile a new version each time I make a new wallpaper. For those who are trying to do the same, I'd like to point out that the version of ffmpeg used in this project requires version 5 of the ndk; version 9 will not compile it correctly.
I've accepted an existing answer instead of adding my own as it does answer the original intent of my question, even if it didn't resolve this specific issue, and I think it could be helpful to other new developers.
If using Eclipse, the proper way to rename the package is to do the following: Right click on project -> Android Tools -> Rename Application Package.
The easiest change would be not to move the NativeCalls class to the new package. This may cause few import statements in Java files that use this class, but your C code can be kept unchanged. You can even use it without recompile.
I am currently writing an application for a client who wants to gather data regarding the signal strength at set intervals.
Currently I am using this code:
private static class MyPhoneStateListener extends PhoneStateListener
{
#Override
public void onSignalStrengthsChanged(SignalStrength signalStrength)
{
super.onSignalStrengthsChanged(signalStrength);
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
InfoStore.setSignal(String.valueOf(signalStrength.getGsmSignalStrength()));
}
};
This works fine, however the client wants the signal strength in both level (I guess how many bars?), DBM, and ASU.
Anyone have any clue how to read the signal strengths using those different forms?
As mentioned by Charles Ma and Kevin Krumwiede the relevant Android methods are hidden (probably for good reason), however it is still possible to get the values by reflection. Thus one solution to original question:
private class MyPhoneStateListener extends PhoneStateListener
{
public static final int INVALID = Integer.MAX_VALUE;
public int signalStrengthDbm = INVALID;
public int signalStrengthAsuLevel = INVALID;
#Override
public void onSignalStrengthsChanged(SignalStrength signalStrength)
{
signalStrengthDbm = getSignalStrengthByName(signalStrength, "getDbm");
signalStrengthAsuLevel = getSignalStrengthByName(signalStrength, "getAsuLevel");
}
private int getSignalStrengthByName(SignalStrength signalStrength, String methodName)
{
try
{
Class classFromName = Class.forName(SignalStrength.class.getName());
java.lang.reflect.Method method = classFromName.getDeclaredMethod(methodName);
Object object = method.invoke(signalStrength);
return (int)object;
}
catch (Exception ex)
{
return INVALID;
}
}
}
In android 4.x the SignalStrength class has getAsuLevel, getDbm, as well as getLevel (bars) methods.
If you need this to work for older android versions, have a look at the source code and you can copy the implementations of those methods over.
http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/4.1.2_r1/android/telephony/SignalStrength.java/
The only thing that you can't get is the Lte measurements in older android versions, but you can probably use java reflection to see if the getLte* methods exist and call it.
Calculate dBm by
int SignalStrength_ASU = signalStrength.getGsmSignalStrength();
int SignalStrength_dBm = (2 * SignalStrength_ASU) - 113; // -> dBm
How can we create a verbose/logging mode in the app which when switched on will print logging statements from the app and on switching it off no log statements will be printed on the console? One way is to create a preferences option and do a ton of if and else, which does not sound very good. Is there a standard way to do it in Android?
I've never done this myself but check here : http://developer.android.com/reference/android/util/Log.html
Under the isLoggable function it mentions how to enable/disable logging for different types (ERROR, INFO, VERBOSE, etc).
That is, if you're okay having this setting in one file and changing that when you need to.
I created a simple Class to do my logs, so I can easily switch it off. I'm sure there's plenty of rooms for improvements, but it works :)
So use this Log Class instead of the android one:
public class Log {
private static String tag = "YOUR_LOG_TAG";
public static void d(String... params){
for(String m : params){
android.util.Log.d(tag, m);
}
}
public static void d(int m){
android.util.Log.d(tag, String.valueOf(m));
}
public static void d(String iTag, String m){
android.util.Log.d(iTag, m);
}
public static void e(String iTag, String m, Throwable t){
android.util.Log.e(iTag, m, t);
}
public static void e(String m, Throwable t){
android.util.Log.e(tag, m, t);
}
public static void e(String iTag, String m){
android.util.Log.e(iTag, m);
}
}
I agree with #nmjohn that using the android logger is the easiest way to do logging. Together with the Eclipse-adt-plugin-view "LogCat" you can decide at runtime, what you want to see from the logging when your device is connected to development-pc via usb.
If you want to write portable busineslogic you can use the Simple Logging Facade for Java(SLF4J). There is already a "do nothig" implementatin and a implementation that uses the android Log mechanism.
If you need a special kind of logging you can easily create your own SLF4J-implementation that can write to a disk file or do something else.
As far as i know the java standard logger log4j does not work for android because of missing dependencies and a memory footprint that is to big for android.