本文共 9602 字,大约阅读时间需要 32 分钟。
最近开发一种功能,在屏幕熄灭之后,监控按键,然后发广播,启动某些应用。
FileObserver 使用过程的大坑 就是权限!两种权限,一种是SD卡的读写权限,一种是android 系统使用这个API的权限
另外,如果想在系统休眠的时候,创建文件和文件夹,需要修改 SE权限,这部分在system/sepolicy ,然后编译boot.img
system/sepolicy$ svn diff .Index: system_server.te===================================================================--- system_server.te (revision 147)+++ system_server.te (working copy)@@ -547,9 +547,14 @@ # Do not allow opening files from external storage as unsafe ejection # could cause the kernel to kill the system_server.-neverallow system_server sdcard_type:dir { open read write };-neverallow system_server sdcard_type:file rw_file_perms;+allow system_server sdcard_type:dir { open read write add_name create_dir_perms};+allow system_server sdcard_type:file {rw_file_perms create_file_perms rename}; ++# avc: denied { add_name } for name="rscjakey2.txt" scontext=u:r:system_server:s0 tcontext=u:object_r:fuse:s0 tclass=dir permissive=0+#avc: denied { write } for name="0" dev="fuse" ino=1 scontext=u:r:system_server:s0 tcontext=u:object_r:fuse:s0 tclass=dir permissive=0+#allow system_server fuse:dir { open read write add_name };+ # system server should never be opening zygote spawned app data # files directly. Rather, they should always be passed via a # file descriptor.
创建的过程是在phonewindowmanger里面的,监控按键,然后创建。
if (keyCode == 139 ) { Log.d(TAG, "5910KeyEvent.KEYCODE_POWER=" + keyCode); if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { Environment.setUserRequired(false); File rscjafile = new File ("/sdcard/rscja"); File txtFile = new File ("/sdcard/rscja/key.txt"); Log.i("keyCode ssss1111 5921 ", " sssssssstxtFile.exists() ="+txtFile.exists()); if(down) { try { Log.i("keyCode ssss1111 5925 ", " sssssssstxtFile.exists() ="+rscjafile.exists()); if (!rscjafile.exists()) { rscjafile.mkdirs(); Log.i("keyCode ssss1111 5928", " sssssssstxtFile.exists() ="+rscjafile.exists()); } Log.i("keyCode ssss 5919 ", " sssssssstxtFile.exists(22222) ="+txtFile.exists()); FileOutputStream outputStream = new FileOutputStream(txtFile); outputStream.write("1".getBytes()); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } }else { try { Log.i("keyCode ssss 5931 ", " sssssssstxtFile.exists(22222) ="+txtFile.exists()); FileOutputStream outputStreamup = new FileOutputStream(txtFile); outputStreamup.write("0".getBytes()); outputStreamup.close(); } catch (IOException e) { e.printStackTrace(); } } } if (repeatCountvv == 0) { Intent myKeyIntent = new Intent(); if(down) { myKeyIntent.setAction("com.KEY_DOWN"); } else { myKeyIntent.setAction("com.EY_UP"); } myKeyIntent.putExtra("keycode", keyCode); mContext.sendBroadcastAsUser(myKeyIntent, UserHandle.ALL); } return 0; }
先贴代码
package com.chww.androidfilelistener;import android.Manifest;import android.app.Activity;import android.app.AlertDialog;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.os.FileObserver;import android.provider.Settings;import android.support.v4.app.ActivityCompat;import android.support.v4.content.ContextCompat;import android.widget.Toast;import static android.content.pm.PackageManager.PERMISSION_GRANTED;public class AndroidFileListenerActivity extends Activity { private FileObserver mFileObserver; private FileObserver multiFileObserver; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myRequetPermission(); if(null == mFileObserver) { mFileObserver = new SDCardFileObserver(getApplicationContext(),Environment.getExternalStorageDirectory().getPath()+"/recja/"); mFileObserver.startWatching(); //开始监听 } } static class SDCardFileObserver extends FileObserver { //mask:指定要监听的事件类型,默认为FileObserver.ALL_EVENTS public SDCardFileObserver(String path, int mask) { super(path, mask); } public SDCardFileObserver(Context ct, String path) { super(path); } @Override public void onEvent(int event, String path) { final int action = event & FileObserver.ALL_EVENTS; switch (action) { case FileObserver.ACCESS: System.out.println("event: 文件或目录被访问, path: " + path); break; case FileObserver.DELETE: System.out.println("event: 文件或目录被删除, path: " + path); break; case FileObserver.OPEN: System.out.println("event: 文件或目录被打开, path: " + path); break; case FileObserver.MODIFY: System.out.println("event: 文件或目录被修改, path: " + path); break; case FileObserver.CREATE: System.out.println("event: 文件或目录被创建, path: " + path); break; } } } private void myRequetPermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, 1); }else { Toast.makeText(this,"您已经申请了权限!",Toast.LENGTH_SHORT).show(); } } private static final int NOT_NOTICE = 2;//如果勾选了不再询问 private AlertDialog alertDialog; private AlertDialog mDialog; @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 1) { for (int i = 0; i < permissions.length; i++) { if (grantResults[i] == PERMISSION_GRANTED) {//选择了“始终允许” Toast.makeText(this, "" + "权限" + permissions[i] + "申请成功", Toast.LENGTH_SHORT).show(); } else { if (!ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i])){//用户选择了禁止不再询问 AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("permission") .setMessage("点击允许才可以使用我们的app哦") .setPositiveButton("去允许", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { if (mDialog != null && mDialog.isShowing()) { mDialog.dismiss(); } Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null);//注意就是"package",不用改成自己的包名 intent.setData(uri); startActivityForResult(intent, NOT_NOTICE); } }); mDialog = builder.create(); mDialog.setCanceledOnTouchOutside(false); mDialog.show(); }else {//选择禁止 AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("permission") .setMessage("点击允许才可以使用我们的app哦") .setPositiveButton("去允许", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { if (alertDialog != null && alertDialog.isShowing()) { alertDialog.dismiss(); } ActivityCompat.requestPermissions(AndroidFileListenerActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); } }); alertDialog = builder.create(); alertDialog.setCanceledOnTouchOutside(false); alertDialog.show(); } } } } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode==NOT_NOTICE){ myRequetPermission();//由于不知道是否选择了允许所以需要再次判断 } }}
配置文件
总结,有很多APK 是需要 android:sharedUserId="android.uid.system" 这个权限才能去做一些事情的~搞了几天才发现的。
没有任何提示啊~~!方向都找不到,只能猜
android 7.1的签名APK 方法
java -Djava.library.path=. -jar signapk.jar platform.x509.pem platform.pk8 app-debug.apk app_sign.apk
demo已经上传
怎么不能设置免积分了。
转载地址:http://yazo.baihongyu.com/