JNI基础02

来源:互联网 发布:剑灵可爱萝莉捏脸数据 编辑:程序博客网 时间:2024/06/04 23:19

真实项目中开发JNI程序的过程:

1.得到so及其开发说明文档;2.根据开发文档写出本地方法;3.加载动态库;4.调用本地方法;

1.模拟美图秀秀的修改图形

1.美图秀秀里面也是调用了C中的方法修改图形的:本地方法,so文件。在java代码中加载动态库,调用本地方法修改图形。步骤:1.反编译mtxx.apk,得到so文件和本地方法的代码,放到自己的工程中;2.创建界面,修改图形:修改图形时调用本地方法修改图形;MainActivity.java:    public class MainActivity extends Activity {        private ImageView iv;        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);            iv = (ImageView) findViewById(R.id.iv);            // 加载美图秀秀的动态库            System.loadLibrary("mtimage-jni");        }       public void update(View v){           // 修改图形,然后把修改后的图形显示在iv上           // 1.得到原图           Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.after2);        // 2.得到原图的颜色数据(数组):计算机或者手机是使用像素点来表示颜色的,一个像素点表示一个颜色值,这些颜色值 是存储在一个数组中,数组中的一个元素就是一个颜色值           int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];           // pixels把图形的颜色数据放到这个数组中           // offset 往数组中写数据的索引位置           //stride  往下一行写数据时跳过的像素点个数           bitmap.getPixels(pixels , 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());           // 3.调用JNI类中的本地方法修改颜色数组           JNI jni = new JNI();           // paramArrayOfInt:颜色数组           // paramInt1,paramInt2 图片的宽和高           jni.StyleLomoC(pixels, bitmap.getWidth(), bitmap.getHeight());           // 4.使用修改后的数组创建一个新的图形           Bitmap newBitmap = Bitmap.createBitmap(pixels, bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());           // 5.把新创建的图形显示在iv上           iv.setImageBitmap(newBitmap);       }

2.锅炉压力表

1.创建柱状的矩形,根据压力值的大小显示柱状的高低和背景色; 压力值:0-180 显示绿色,180-220 显示黄色,220-250显示红色,250以上就提示快跑2.在c中模拟返回压力值(随机的数字);3.在java中调用本地方法;在C语言中随机生成一个数字,%300表示始终小于300int getPresure() {    return rand() % 300;}

MainActivity.java:

public class MainActivity extends Activity {    private Timer timer;    private TimerTask task;    static{        // 加载动态库        System.loadLibrary("PresureDemo");    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);//        setContentView(R.layout.activity_main);        timer = new Timer();        task = new TimerTask() {            // 是运行在子线程中的            @Override            public void run() {                runOnUiThread(new Runnable() {                    @Override                    public void run() {                         // 调用本地方法得打压力值                        int presure = getPresure();                        if(presure<250){                             PresureView view = new PresureView(MainActivity.this,presure);                              setContentView(view);                        }else{                            TextView tv =new TextView(MainActivity.this);                            tv.setText("哥哥,锅炉快爆炸了,赶快跑!!!!!!!!!");                            tv.setTextColor(Color.RED);                            tv.setTextSize(25);                            setContentView(tv);                            timer.cancel();                            task.cancel();                            timer = null;                            task = null;                        }                    }                });            }        };        timer.schedule(task, 1000, 500);    }   public native int getPresure();}

PresureView.java:

public class PresureView extends View {    private Paint paint;    private int mPresure;    public PresureView(Context context,int presure) {        super(context);        // 创建画笔        paint = new Paint();        // 接收activity传过来的压力值        mPresure = presure;    }    /**     * 界面打开时系统会调用这个方法绘制图形,显示界面     */    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if(mPresure < 180){            // 设置画笔的颜色,也是设置矩形的背景色            paint.setColor(Color.GREEN);        }else if(mPresure < 220){            // 设置画笔的颜色,也是设置矩形的背景色            paint.setColor(Color.YELLOW);        }else if(mPresure < 250){            // 设置画笔的颜色,也是设置矩形的背景色            paint.setColor(Color.RED);        }else{            System.out.println("=========提示快跑======");        }        // 绘制矩形        canvas.drawRect(20, 300-mPresure, 40, 300, paint);    }}

PresureDemo.c:

#include <stdio.h>#include <stdlib.h>#include "com_itheima_presuredemo_MainActivity.h"int getPresure(){  return rand()%300;}JNIEXPORT jint JNICALL Java_com_itheima_presuredemo_MainActivity_getPresure  (JNIEnv * env, jobject obj){    // 返回一个随机的数字    return getPresure();}

3.卸载应用打开浏览器

软件被卸载后使用浏览器打开一个网页,让用户参数反馈。fork():分叉方法,可以从父进程中分裂出一个子进程(相当于一个子线程,自己独立运行)。在软件卸载之前调用c中的一个方法,在方法中调用fork函数,当fork返回为0时,检测/data/data/包名的目录是否存在,如果存在说明软件没有被卸载,否则说明该软件已经被卸载了。如果软件被卸载,就是用浏览器打开一个网页。步骤:1.在java代码中创建本地方法;2.c文件中写一个方法,在方法中调用fork函数3.当fork返回为0时,每隔1秒钟就检测/data/data/包名的目录是否存在,如果存在说明软件没有被卸载,否则说明该软件已经被卸载了。4.如果软件被卸载,就是用浏览器打开一个网页;

AppUninstallDemo.c:

#include <stdio.h>#include <stdlib.h>#include "com_itheima_appuninstalldemo_MainActivity.h"JNIEXPORT void JNICALL Java_com_itheima_appuninstalldemo_MainActivity_uninstallApp  (JNIEnv * env, jobject obj){    // 使用这个变量来控制是否继续监测    int isStop = 0;    // 调用分叉函数,分裂进程    int result = fork();    if(result > 0){        //在父进程中    }else  if(result == 0){        isStop = 1;        //每隔1秒钟就检测/data/data/包名的目录是否存在,如果存在说明软件没有被卸载,否则说明该软件已经被卸载了。        while(isStop){            // 睡眠1秒            sleep(1);            // 得到/data/data/包名的目录            FILE* file = fopen("/data/data/com.itheima.appuninstalldemo","r");            if(file == NULL){                //说明该软件已经被卸载了,使用浏览器打开一个网页                execlp("am", "am", "start", "-a", "android.intent.action.VIEW", "-d", "http://www.itheima.com", NULL);                // 置为0表示下次不再继续while循环了,不再监测了                isStop = 0;            }        }    }}

进程:是应用程序的载体; 在软件一启动的时候linux系统就会给它创建一个进程,用来运行delvik虚拟机的,而我们的应用程序就是运行在虚拟机中。

0 0
原创粉丝点击