分享

Android JNI Lame编解码实现wav到MP3的转换

 苦修茶馆 2016-02-15
1、JNI简介

JNI全称为Java Native Interface(JAVA本地调用)。从Java1.1开始,JNI成为java平台的一部分,它允许Java代码和其他语言写的代码(如C&C++)进行交互。并非从Android发布才引入JNI的概念的。

2、JNI与NDK

简单来说,Android的NDK提供了一些交叉编译工具链和Android自带的库,这些Android的库可以让开发者在编写本地语言的程序时调用。而NDK提供的交叉编译工具链就对已经编写好的C&C++代码进行编译,生成库。

当然了,你也可以自己搭建交叉编译环境,而不用NDK的工具和库。然后生成库,只要规范操作,一样可以生成能让JAVA层成功调用的库文件的。


   
[AppleScript] 纯文本查看 复制代码
1
使用JNI技术,其实就是在Java程序中,调用C语言的函数库中提供的函数,来完成一些Java语言无法完成的任务。由于Java语言和C语言结构完全不相同,因此若想让它们二者交互,则需要制定一系列的规范。JNI就是这组规范,此时    Java只和JNI交互,而由JNI去和C语言交互。

JNI技术分为两部分:Java端和C语言端。且以Java端为主导。

|- 首先,Java程序员在Java端定义一些native方法,并将这些方法以C语言头文件的方式提供给C程序员。

|- 然后,C程序员使用C语言,来实现Java程序员提供的头文件中定义的函数。

|- 接着,C程序员将函数打包成一个库文件,并将库文件交给Java程序员。


在Java程序执行的时候,若在某个类中调用了native方法,则虚拟机会通过JNI来转调用库文件中的C语言代码。提示:C代码最终是在Linux进程中执行的,而不是在虚拟机中。

下面是一个Android调用JNI实现通过LAME转码器实现wav格式到MP3格式的转换.

准备:首先下载lame源码文件。

需要三个条件 :cgywin,cdt,ndk才能实现JNI的开发。

开发lame需要从 http://lame./ 选择Using Lame 下载源代码。


新建工程1、Android主界面布局

[XML] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas./apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <EditText
  android:id="@+id/editText1"
  android:hint="源wav文件的路径"
  android:text="/sdcard/118/ccc.wav"
  android:layout_width="match_parent"
  android:layout_height="wrap_content" >
    </EditText>
    <EditText
  android:id="@+id/editText2"
    android:hint="目标MP3文件的路径"
  android:layout_width="match_parent"
    android:text="/sdcard/118/ccccc.mp3"
  android:layout_height="wrap_content" />
    <Button
  android:id="@+id/button1"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="转化"
  android:onClick="convert"
  />
    <Button
  android:id="@+id/button2"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="获取lame版本号"
  android:onClick="getversion"
   />
</LinearLayout>

首先是建立JNI目录

1、把lameC语言源码导入jni中2、创建Android.mk文件

[AppleScript] 纯文本查看 复制代码
1
2
3
4
5
6
7
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := Hello
LOCAL_SRC_FILES := bitstream.c fft.c id3tag.c mpglib_interface.c presets.c  quantize.c   reservoir.c tables.c  util.c  VbrTag.c encoder.c  gain_analysis.c lame.c  newmdct.c   psymodel.c quantize_pvt.c set_get.c  takehiro.c vbrquantize.c version.c Hello.c
LOCAL_LDLIBS += -llog
include $(BUILD_SHARED_LIBRARY)

3、编写C语言文件

[C++] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <stdio.h>
#include <jni.h>
#include "com_example_ndkpassdata_DataProvider.h"
#include <android/log.h>
#include<malloc.h>
#define LOG_TAG "System.out.c"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
char* Jstring2CStr(JNIEnv* env, jstring jstr) {
    char* rtn = NULL;
    jclass clsstring = (*env)->FindClass(env, "java/lang/String"); //String
    jstring strencode = (*env)->NewStringUTF(env, "GB2312"); // 得到一个java字符串 "GB2312"
    jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes",
      "(Ljava/lang/String;)[B"); //[ String.getBytes("gb2312");
    jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid,
      strencode); // String .getByte("GB2312");
    jsize alen = (*env)->GetArrayLength(env, barr); // byte数组的长度
    jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);
    if (alen > 0) {
  rtn = (char*) malloc(alen + 1);    //"\0"
  memcpy(rtn, ba, alen);
  rtn[alen] = 0;
    }
    (*env)->ReleaseByteArrayElements(env, barr, ba, 0);  //
    return rtn;
}
JNIEXPORT jint JNICALL Java_com_example_ndkpassdata_DataProvider_add(
  JNIEnv *env, jobject obj, jint x, jint y) {
    LOGD("x=%d", x);
    LOGD("y=%d", y);
    return x + y;
}
JNIEXPORT jstring JNICALL Java_com_example_ndkpassdata_DataProvider_sayHelloInc(
  JNIEnv *env, jobject obj, jstring jstr) {
    char *cstr = Jstring2CStr(env, jstr);
    LOGD("cstr=%s", cstr);
    char arr[7] = { ' ', 'h', 'e', 'l', 'l', 'o', '/0' };
    strcat(cstr, arr);
    LOGD("newcstr=%s", cstr);
    return (*env)->NewStringUTF(env, cstr);
}
JNIEXPORT jintArray JNICALL Java_com_example_ndkpassdata_DataProvider_intMethod(
  JNIEnv *env, jobject obj, jintArray arr) {
    int len = (*env)->GetArrayLength(env, arr);
    LOGD("SHUZU length-=%d", len);
    jint *intarr = (*env)->GetIntArrayElements(env, arr, 1);
    int i = 0;
    for (; i < len; i++) {
  LOGD("intarr[%d]=%d", i, intarr[i]);
  *(intarr + i) += 10;
  //intarr[i] += 10;
    }
    (*env)->ReleaseIntArrayElements(env, arr, intarr, len);
    return arr;
}
JNIEXPORT jint JNICALL Java_com_example_ndkpassdata_DataProvider_sub(
  JNIEnv *env, jclass clazz, jint x, jint y) {
    LOGD("x=%d", x);
    LOGD("Y=%d", y);
    return x - y;
}

4、使用cgywin工具进行ndk-build编译

成功之后

5、编写Activity文件


[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package cn.itcast.lame;
import java.io.File;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class LameActivity extends Activity {
  private EditText et_wav;
  private EditText et_mp3;
  private ProgressDialog pd;
  public native void convertmp3(String wav,String mp3);
  public native String getLameVersion();
  public native void stop();
  static{
    System.loadLibrary("Hello");
  }
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    et_wav =  (EditText) this.findViewById(R.id.editText1);
    et_mp3 = (EditText) this.findViewById(R.id.editText2);
    pd = new ProgressDialog(this);
  }
  public void convert(View view){
    final String mp3name = et_mp3.getText().toString().trim();
    final String wavname = et_wav.getText().toString().trim();
    File file = new File(wavname);
    int size = (int) file.length();
    System.out.println("文件大小 "+ size);
    if("".equals(mp3name)||"".equals(wavname)){
      Toast.makeText(this, "路径不能为空", 1).show();
      return;
    }
    //convertmp3(wavname,mp3name);
    pd.setMessage("转换中....");
    pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    pd.setMax(size); // 设置进度条的最大值
    //pd.setCancelable(false);
    pd.show();
    new Thread(){
      @Override
      public void run() {
        convertmp3(wavname,mp3name);
        pd.dismiss();
      }
    }.start();
  }
  public void setConvertProgress(int progress){
    pd.setProgress(progress);
  }
  public void getversion(View view){
    String version = getLameVersion();
    Toast.makeText(this, version, 0).show();
  }
}

6、运行程序

源码地址:

http://download.csdn.net/detail/kai46385076/8999373

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多