android jni 广播,APP在接到系统发出的shake的broadcast时启动,之后通过JNI读取/proc/meminfo...

在framework层满足条件时发广播,app层接收广播并调用jni层读取/proc/meminfo文件

1>framework层

先来大概介绍下android的几个层,从下到上依次是:kernel,hal,jni,framework,app

Java应用程序通过JNI(java native interface)来调用硬件抽象层接口

framework用来提供app的一些service,层位于源码的/framework/下

下面我们来实现在framework层发广播,包括判断发广播条件,以及确定接收广播对象

①先来找到framework下一个比教简单的service文件进行修改,

自己新建也可以,但是修改别人的肯定更简单些

少去了添加编译信息及mk文件等步骤,找到合适的service文件添加内容即可

这里我找到了/frameworks/base/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java文件

先来导入一些包

import android.content.Context;

import com.android.server.AppWidgetBackupBridge;

import com.android.server.SystemService;

import android.content.Intent;

import android.hardware.Sensor;

import android.hardware.SensorEvent;

import android.hardware.SensorEventListener;

import android.hardware.SensorManager;

private Context context;

private SensorManager sensorManager;

private Sensor sensor;

②来获取重力传感器

这几步分别是,

获取sensormanager,

通过sensormanager获取加速度传感器即重力传感器

通过new出自己定义的myGsensorListener类,设置sensor的监听,SensorManager.SENSOR_DELAY_GAME参数是设置刷新速度使sensor适应当前game

private void setSernorHandle() {

System.out.println("--------start ShandeActivity-------");

sensorManager=(SensorManager)context.getSystemService(context.SENSOR_SERVICE);

sensor= sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

sensorManager.registerListener(new myGsensorListener(), sensor,SensorManager.SENSOR_DELAY_GAME);

}

③判断发广播条件及发广播

下面来实现myGsensorListener类,他是继承于sensorEventListener的

onAccuracyChanged方法虽然用不到,但是由于是继承父类,必须要有

Intent intent=new Intent("android.jessie.action");是设置接收boradcast的intent对象,

其中的android.jessie.action是在app的manifest的reciver中定义的,

context.sendBroadcast(intent);是发广播

class myGsensorListener implements SensorEventListener

{

@Override

public void onSensorChanged(SensorEvent event) {

int sensorType = event.sensor.getType();

//values[0]:X轴,values[1]:Y轴,values[2]:Z轴

float[] values = event.values;

if (sensorType == Sensor.TYPE_ACCELEROMETER)

{

if ((Math.abs(values[0]) > 17 || Math.abs(values[1]) > 17 || Math

.abs(values[2]) > 17))

{

Log.d("sensor x ", "============ values[0] = " + values[0]);

Log.d("sensor y ", "============ values[1] = " + values[1]);

Log.d("sensor z ", "============ values[2] = " + values[2]);

//Toast.makeText(getApplicationContext(), "Sensor Change Event", Toast.LENGTH_SHORT).show();

Intent intent=new Intent("android.jessie.action");

context.sendBroadcast(intent);

System.out.println("--------Sensor Change Event-------");

}

}

}

@Override

public void onAccuracyChanged(Sensor sensor, int accuracy) {

// TODO Auto-generated method stub

}

}

}push去

2>APP层

由于app需要调用到JNI的文件,所以需要提前配置好NDK

①Shake manifest

工程配置文件设置了app_name等属性,并设置主界面MainActivity

广播recive,reciver的name就是broadcast中的android.jessie.action,app就是通过这里来接收广播的,并调用MyReciver.java

package="com.example.shake"

android:versionCode="1"

android:versionName="1.0" >

android:minSdkVersion="19"

android:targetSdkVersion="21" />

android:allowBackup="true"

android:icon="@drawable/ic_launcher"

android:label="@string/app_name"

android:theme="@style/AppTheme" >

android:name=".MainActivity"

android:label="@string/app_name"/>

②MyReciver.java

通过Intent intent1 = new Intent(context, MainActivity.class);指定MainActivity为目标

context.startActivity(intent1); 即在接收广播后启动主界面

package com.example.shake;

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.Intent;

public class MyReciver extends BroadcastReceiver{

@Override

public void onReceive(Context context, Intent intent) {

Intent intent1 = new Intent(context, MainActivity.class);

intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

context.startActivity(intent1);

}

}

③MainActivity.java

MyReciver.java接收到广播启动主界面后调用MainActivity.java

textView=(TextView)findViewById(R.id.tv_test1);是设置文本显示内容,内容id是id.tv_test1

然后调用NativeReadMem类的readMem方法来设置显示内容

package com.example.shake;

import android.app.Activity;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

import android.widget.TextView;

public class MainActivity extends Activity {

private TextView textView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

textView=(TextView)findViewById(R.id.tv_test1);

System.out.println("Read meminfo:-"+NativeReadMem.readMem());

textView.setText(NativeReadMem.readMem());

}

}

ps: activity_main.xml

中定义了id.tv_test1的属性

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="fill_parent"

android:layout_height="match_parent"

>

android:layout_height="wrap_content"

>

android:id="@+id/tv_test1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/hello_world" />

NativeReadMem.java

这便是java调用jni的接口类

System.loadLibrary("ReadmemInfo");引入ReadmemInfo模块

package com.example.shake;

public class NativeReadMem {

public native static String readMem() ;

static{

System.loadLibrary("ReadmemInfo");

}

}

⑤ReadmemInfo

0818b9ca8b590ca3270a3433284dd417.png

通过上述命令在app工作目录生成jni文件夹以及对应的.h文件

step1.com_example_shake_NativeReadMem.h

/* DO NOT EDIT THIS FILE - it is machine generated */

#include

/* Header for class com_example_shake_NativeReadMem */

#ifndef _Included_com_example_shake_NativeReadMem

#define _Included_com_example_shake_NativeReadMem

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: com_example_shake_NativeReadMem

* Method: readMem

* Signature: ()Ljava/lang/String;

*/

JNIEXPORT jstring JNICALL Java_com_example_shake_NativeReadMem_readMem

(JNIEnv *, jclass);

#ifdef __cplusplus

}

#endif

#endif

step2. com_example_shake_NativeReadMem.c

去读取/proc/meminfo文件并返回读取内容

#include "com_example_shake_NativeReadMem.h"

#include

#include

#include

#include

JNIEXPORT jstring JNICALL Java_com_example_shake_NativeReadMem_readMem

(JNIEnv *env, jclass obj){

FILE *pFile=fopen("/proc/meminfo","r"); //获取文件的指针

char pBuf[2048]={0}; //定义文件指针

char * tempbuf;

int len=0;

tempbuf=(char *)malloc(101);

if(pFile!=(FILE*)NULL)

{

while(!feof(pFile)){

fgets(tempbuf,100,pFile);

strcpy(pBuf+len,tempbuf);

len=len+strlen(tempbuf);

}

}

free(tempbuf);

fclose(pFile);

return (*env)->NewStringUTF(env, pBuf);

}

step3. Android.mk

其中的LOCAL_MODULE    := ReadmemInfo就是NativeReadMem.java中所引入的库名

NativeReadMem.java也就是通过ReadmemInfo来调用jni模块的

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := ReadmemInfo

LOCAL_SRC_FILES := com_example_shake_NativeReadMem.c

include $(BUILD_SHARED_LIBRARY)

大功告成~~

结果是摇动就会跳出app界面,显示/proc/meminfo内容

效果图

0818b9ca8b590ca3270a3433284dd417.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值