Android安全和权限①----ShareUserId和文件访问(File Access)--Security and Permission

本文详细介绍了如何利用SharedUserId实现两个Android应用程序之间的资源共享。通过配置manifest文件并设置相同的SharedUserId,可以使不同应用之间互相访问文件和数据。

关于SharedUserId的总结:

 我们知道一般每个app都有一个唯一的linux user ID,则这样权限就被设置成该应用程序的文件只对该用户可见,只对该应用程序自身可见,而我们可以使他们对其他的应用程序可见,这会使我们用到 SharedUserId,也就是让两个apk使用相同的userID,这样它们就可以看到对方的文件。为了节省资源,具有相同ID的apk也可以在相同 的linux进程中进行(这儿需要注意,并不是一定要在一个进程里面运行),共享一个虚拟机。

我们可以建立两个application,分别为test_a和test_b,我们的目的就是让test_b访问test_a里面的文件或者是数据:具体做法如下

在test_a应用程序的包com.test1的manifest里面添加anroid:shareuserid=“com.test2”(注:这 儿test_a是被访的apk,so 加上这句  android:exported="false"说明它是私有的,然后会让shareuserid应用更有力)

具体内容如下:

  1. <? xml   version = "1.0"   encoding = "utf-8" ?>   
  2. < manifest   xmlns:android = "http://schemas.android.com/apk/res/android"   
  3.       package = "com.test1"   
  4.       android:sharedUserId = "com.test2"   
  5.       android:exported = "false"   
  6.       android:versionCode = "1"   
  7.       android:versionName = "1.0" >   
  8.     < application   android:icon = "@drawable/icon"   android:label = "@string/app_name" >   
  9.         < activity   android:name = ".TestAcitvity1"   
  10.                   android:label = "@string/app_name" >   
  11.             < intent-filter >   
  12.                 < action   android:name = "android.intent.action.MAIN"   />   
  13.                 < category   android:name = "android.intent.category.LAUNCHER"   />   
  14.             </ intent-filter >   
  15.         </ activity >   
  16.     </ application >   
  17.   
  18.   
  19. </ manifest >    

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.test1" android:sharedUserId="com.test2" android:exported="false" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".TestAcitvity1" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>

然后再应用程序test_b的包com.test2下的manifest.xml中添加anroid:shareuserid=“com.test2”

然后在test_b的TestActivity2中添加如下代码:

  1. private  Button.OnClickListener button_listener =  new  Button.OnClickListener() {  
  2.         public   void  onClick(View v) {  
  3.             Intent intent = new  Intent();  
  4.               
  5.             intent.setClassName("us.imnet.iceskysl.db" , "us.imnet.iceskysl.db.DBSharedPreferences" );  
  6.             //intent.setClassName("com.test1","com.test1.TestActivity1");   
  7.   
  8.               
  9.             startActivity(intent);  
  10.         }  
  11.     };  

private Button.OnClickListener button_listener = new Button.OnClickListener() { public void onClick(View v) { Intent intent = new Intent(); intent.setClassName("us.imnet.iceskysl.db","us.imnet.iceskysl.db.DBSharedPreferences"); //intent.setClassName("com.test1","com.test1.TestActivity1"); startActivity(intent); } };

这样就可以调整跳转,然后就可以运行。完整代码是:

  1. package  com.test2;  
  2.   
  3. import  android.app.Activity;  
  4. import  android.content.Intent;  
  5. import  android.os.Bundle;  
  6. import  android.view.View;  
  7. import  android.widget.Button;  
  8.   
  9. public   class  TestActivity2  extends  Activity {  
  10.     /** Called when the activity is first created. */   
  11.     @Override   
  12.     public   void  onCreate(Bundle savedInstanceState) {  
  13.         super .onCreate(savedInstanceState);  
  14.         setContentView(R.layout.main);  
  15.         find_and_modify_button();  
  16.     }  
  17.     private   void  find_and_modify_button(){  
  18.         Button change_test1 = (Button) findViewById(R.id.change_test1);  
  19.         change_test1.setOnClickListener(button_listener);  
  20. }  
  21.     private  Button.OnClickListener button_listener =  new  Button.OnClickListener() {  
  22.         public   void  onClick(View v) {  
  23.             Intent intent = new  Intent();  
  24.               
  25.             intent.setClassName("us.imnet.iceskysl.db" , "us.imnet.iceskysl.db.DBSharedPreferences" );  
  26.             //intent.setClassName("com.test1","com.test1.TestActivity1");   
  27.   
  28.               
  29.             startActivity(intent);  
  30.         }  
  31.     };  
  32. }  

package com.test2; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; public class TestActivity2 extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); find_and_modify_button(); } private void find_and_modify_button(){ Button change_test1 = (Button) findViewById(R.id.change_test1); change_test1.setOnClickListener(button_listener); } private Button.OnClickListener button_listener = new Button.OnClickListener() { public void onClick(View v) { Intent intent = new Intent(); intent.setClassName("us.imnet.iceskysl.db","us.imnet.iceskysl.db.DBSharedPreferences"); //intent.setClassName("com.test1","com.test1.TestActivity1"); startActivity(intent); } }; }

运行结果是:从test_b的TestActivity1中进去,然后跳到TestActivity2中,这样可以读取到它里面的数据出来

文件访问:

可以通过getSharedPreferences(String, int) , openFileOutput(String, int) 或者 openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory) 创建一个新文件时, 你可以同时或分别使用 MODE_WORLD_READABLE MODE_WORLD_WRITEABLE 标志允许其它包读 / 写此文件。

下面是用getSharedPreferences(String, int) ,创建到文件,修改它的属性为MODE_WORLD_WRITEABLE 则看到它的文件权限的变化:

(补充):关于linux下面文件权限

第2~10个字符当中的每3个为一组,左边三个字符表示所有者权限,中间3个字符表示与所有者同一组的用户的权限,右边3个字符是其他用户的权限。这三个一组共9个字符,代表的意义如下:   
r(Read,读取):对文件而言,具有读取文件内容的权限;对目录来说,具有浏览目 录的权限。   
w(Write,写入):对文件而言,具有新增、修改文件内容的权限;对目录来说,具有删除、移动目录内文件的权限。   
x(eXecute,执行):对文件而言,具有执行文件的权限;对目录了来说该用户具有进入目录的权限。   
-:表示不具有该项权限

<think>好的,用户现在遇到了Android构建错误,主要问题是他们使用的build-tools 23.0.3android-23版本较低,导致无法识别些新属性,比如networkSecurityConfigrequestLegacyExternalStorage,还有主题样式找不到。需要生成个兼容这个旧版本的AndroidManifest.xml。 首先,我需要回顾用户之前提供的AndroidManifest.xml内容,看看哪些部分导致了错误。之前的错误信息显示,AndroidManifest.xml中使用了新版本才有的属性,比如networkSecurityConfigrequestLegacyExternalStorage,这些在API 23及以下版本是不支持的。此外,主题样式如@style/UnityTheme@style/FanweiDialogActivityTheme在资源中未定义,导致构建失败。 用户现在希望生成个兼容build-tools 23.0.3android-23的版本,所以需要移除所有不兼容的属性,并确保所有引用的资源都存在。同时,用户可能还需要保留必要的功能,比如热更新、微信支付集成等。 接下来,我需要调整AndroidManifest.xml,删除或替换那些需要更高API版本的属性。例如,移除networkSecurityConfigrequestLegacyExternalStorage,因为它们在Android 6.0(API 23)中不可用。同时,检查所有使用的权限是否正确,特别是那些在旧版本中可用的权限,避免使用maxSdkVersion导致某些权限被排除。 关于主题样式的问题,用户需要定义缺失的样式。由于用户可能没有提供相应的资源文件,我需要指导他们创建styles.xml文件,并定义所需的样式,比如UnityTheme、FanweiDialogActivityTheme等,确保这些样式基于兼容库的父主题,如Theme.AppCompat。 另外,用户可能在使用FileProvider,而旧版本可能需要使用android.support.v4.content.FileProvider而不是androidx.core.content.FileProvider,所以需要检查并替换正确的类名,确保兼容性。 还需要检查是否有其他新引入的标签或属性在API 23中不支持,比如某些meta-data或activity的属性。确保所有使用的组件配置都与目标SDK版本兼容。 最后,可能需要调整Gradle配置,确保使用的compileSdkVersiontargetSdkVersion不超过23,以避免引入更高版本的功能。同时,建议用户升级构建工具目标SDK版本,如果可能的话,以获得更好的兼容性安全性,但用户当前需求是保持兼容旧版本,所以需要给出相应的解决方案。 总结步骤: 1. 移除所有仅在API 24+支持的属性。 2. 替换FileProvider为旧版本支持的类。 3. 定义缺失的主题样式。 4. 确保所有权限功能兼容API 23。 5. 提供配套的资源文件,如styles.xml必要的图片、字符串资源。 6. 给出Gradle配置建议,确保SDK版本致。</think>以下是针对 **build-tools 23.0.3 + android-23** 的兼容性 AndroidManifest.xml 模板: ```xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.dw.Dating.lua" android:installLocation="preferExternal"> <!-- 基础屏幕适配 --> <supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:smallScreens="true" android:xlargeScreens="true" /> <!-- OpenGL ES 2.0支持 --> <uses-feature android:glEsVersion="0x20000" android:required="false" /> <!-- 核心权限 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.VIBRATE" /> <!-- 存储权限(兼容API 23) --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <!-- 网络状态权限 --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <!-- 触摸屏功能声明 --> <uses-feature android:name="android.hardware.touchscreen" android:required="false" /> <uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" /> <uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" /> <application android:hardwareAccelerated="true" android:icon="@drawable/app_icon" android:isGame="true" android:label="@string/app_name" android:name="com.dw.Dating.wxapi.App"> <!-- 服务器配置 --> <meta-data android:name="URL_VALUE" android:value="http://yourdomain.com" /> <meta-data android:name="CHANNEL" android:value="Official" /> <meta-data android:name="FW_VALUE" android:value="FW-30855784" /> <meta-data android:name="UMENG_APPKEY" android:value="UmengKey" /> <!-- 微信配置 --> <meta-data android:name="AppID" android:value="wx401c37330dd3e92e" /> <!-- 主游戏Activity --> <activity android:name="com.dw.Dating.wxapi.MainActivity" android:configChanges="locale|fontScale|keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode" android:launchMode="singleTask" android:screenOrientation="landscape"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LEANBACK_LAUNCHER" /> </intent-filter> <meta-data android:name="unityplayer.UnityActivity" android:value="true" /> <meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="false" /> </activity> <!-- 支付SDK Activity --> <activity android:name="com.fanwei.jubaosdk.cashier.CashierActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:launchMode="singleTask" android:theme="@android:style/Theme.Dialog" /> <activity android:name="com.fanwei.jubaosdk.wap.WapActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:launchMode="singleTop" android:screenOrientation="portrait" android:theme="@android:style/Theme.Light.NoTitleBar" /> <!-- 文件提供器(兼容旧版FileProvider) --> <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.fileProvider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths_fanwei" /> </provider> <!-- 支付相关Activity --> <activity android:name="com.pay.sdk.usage.PayActivity" android:screenOrientation="portrait" /> <activity android:name="sdk.pay.PayWebViewActivity" android:screenOrientation="portrait" /> <activity android:name="com.switfpass.pay.activity.QQWapPayWebView" android:screenOrientation="portrait" android:theme="@android:style/Theme.Translucent.NoTitleBar" /> <!-- 微信回调Activity --> <activity android:name="com.dw.Dating.lua.wxapi.WXEntryActivity" android:exported="true" android:launchMode="singleTop" android:screenOrientation="portrait" android:theme="@android:style/Theme.NoDisplay" /> </application> </manifest> ``` --- ### 📁 **配套资源文件** #### 1. `styles.xml`(res/values/) ```xml <resources> <!-- 兼容旧版主题 --> <style name="UnityTheme" parent="android:Theme.Holo.Light.NoActionBar"> <item name="android:windowNoTitle">true</item> </style> <style name="FanweiDialogActivityTheme" parent="android:Theme.Holo.Dialog"> <item name="android:windowNoTitle">true</item> </style> <style name="FanweiActivityTheme" parent="android:Theme.Holo.Light"> <item name="android:windowNoTitle">true</item> </style> </resources> ``` #### 2. `file_paths_fanwei.xml`(res/xml/) ```xml <?xml version="1.0" encoding="utf-8"?> <paths> <!-- 限制热更新文件访问范围 --> <external-path name="hotfix" path="." /> </paths> ``` --- ### 🛠️ **关键修改说明** | 修改点 | 说明 | |-------|------| | **移除不兼容属性** | 删除 `networkSecurityConfig` `requestLegacyExternalStorage` | | **降级 FileProvider** | 使用 `android.support.v4.content.FileProvider` 替代 `androidx` | | **主题样式降级** | 使用 `Theme.Holo` 系列替代 `AppCompat` 主题 | | **存储权限** | 移除 `maxSdkVersion`,全部使用原始存储权限 | | **外部路径** | 将 `external-files-path` 改为 `external-path` 兼容旧版 | --- ### 📝 **Gradle 配置建议** ```gradle android { compileSdkVersion 23 buildToolsVersion "23.0.3" defaultConfig { minSdkVersion 16 targetSdkVersion 23 } } ``` --- ### ✅ **构建前检查清单** 1. **图标资源**:确保 `res/drawable/app_icon.png` 存在 2. **字符串资源**:添加 `res/values/strings.xml`: ```xml <resources> <string name="app_name">Your Game</string> </resources> ``` 3. **微信SDK**:确认 `libammsdk.jar` 已放入 `libs/` 目录 4. **混淆规则**:添加 `proguard-rules.pro`: ```proguard -keep class com.dw.Dating.** { *; } -keep class com.fanwei.** { *; } -keep class com.tencent.mm.sdk.** { *; } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值