android 7.1 FileObserver 使用过程的大坑

最近开发一种功能,在屏幕熄灭之后,监控按键,然后发广播,启动某些应用。  

 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();//由于不知道是否选择了允许所以需要再次判断
        }
    }

}

 

 

配置文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.chww.androidfilelistener"
    android:sharedUserId="android.uid.system">
    <!-- SDCard中创建与删除文件权限 -->

    <!-- 向SDCard写入数据权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".AndroidFileListenerActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

 

 

 

总结,有很多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已经上传

怎么不能设置免积分了。

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值