如果您对转载:关于android一键新机,改机概述xposed改机优缺点感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于转载:关于android一键新机,改机概述xposed
如果您对转载:关于android 一键新机,改机概述 xposed 改机优缺点感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于转载:关于android 一键新机,改机概述 xposed 改机优缺点的详细内容,我们还将为您解答android改机系列的相关问题,并且为您提供关于20-2第一篇:关于android对话框、Android 11 安装EdXposed + Magisk框架、Android 7.0及其以上系统拍照,打开相册,裁剪,报错: android.os.FileUriExposedException、Android android:exported = true 用法详解的有价值信息。
本文目录一览:- 转载:关于android 一键新机,改机概述 xposed 改机优缺点(android改机系列)
- 20-2第一篇:关于android对话框
- Android 11 安装EdXposed + Magisk框架
- Android 7.0及其以上系统拍照,打开相册,裁剪,报错: android.os.FileUriExposedException
- Android android:exported = true 用法详解
转载:关于android 一键新机,改机概述 xposed 改机优缺点(android改机系列)
目前,android系统的一键新机,改机模块(应用变量,008,深海等)基本上都是基于xposed框架。先安装xposed框架,再安装改机APP。本文以Xposed框架的实现原理总结此方法改机的缺点:
Xposed框架实现Hook的原理介绍: Zygote进程是 Android 的核心,每运行一个 app,Zygote 就会 fork 一个虚拟机实例来运行 app。Zygote 的启动配置在/init.rc 脚本中,由系统启动的时候开启此进程,对应的执行文件是/system/bin/app_process,这个文件完成类库加载及一些函数调用的工作。当系统中安装了 Xposed 框架 之后,会对 app_process 进行扩展,也就是说,Xposed 框架会拿自己实现的 app_process 覆盖掉 Android 原生提供的 app_process 文件,当系统启动的时候,就会加载由 Xposed Framework 替换过的进程文件。类似于切面编程,当调用java层android接口时,Xposed在接口层下实现一个hook, 如beforeHookedMethod和afterHookedMethod(在调用android JAVA方法前和后实现一个自定义的hook method)
从以上的原理简介看:
Xposed需要替换/system/bin/app_process,因此需要手机获得root权限;
Xposed 实现的hook在java层,只能修改通过JAVA层获取的设备参数。
手机需要安装XposedInstaller.apk;
xposed 是切面编程,对于每一次的JAVA调用,都会执行Xposed的hook函数,对系统性能有较大影响。
对于刷流量,刷广告或者各种养号来说,手机是否root,获取设备参数的不一致都严重影响到转化率,甚至最近常常被秒封号。
手机root的检测:
1) 虽然xposed 有RootCloak(Root隐藏),称能够让针对特定的APP,将设备已经ROOT了的这个特征隐藏起来,从而达到在ROOT的情况下继续使用这些APP的目的。这也只是xposed的一厢情愿而已。对于专业的第三方检查工具或者大型的游戏公司一般都有专门的反作弊研究人员,对于此类型的Root隐藏很容易便能检测出来。
对于RootCloak功能,以及其它的root隐藏功能原理都差不多: 首先需要选择对那个APP隐藏root, 其次需要枚举出所有可能检测系统root功能的地方加入hook函数以欺骗app, 如当检测root的APP执行shell 命令 system/bin/su时,返回此命令不存在,以此来欺骗app系统没有su命令。 对于检测APP来说,检测的点很多,而且检测APP随时再更新。而root隐藏功能必须在检测的每个点设置hook,而且随时跟进app的更新而变化,只要溜掉一个点,隐藏就失败了。 root隐藏是盾,只是被动的防御;检测app是矛。检测的矛总是变换着刺向不同位置,总会有一次盾会防御失败。
要能隐藏root功能,除非系统本就是没有root,否则很难防御。
2)xposed 是对虚拟机的hook, xposed只修改了通过JAVA层获取的设备参数,java层获取设备信息只是android标准的获取方式,还有多种获取设备信息的方法,专业的检查工具通常会通过jni调用,同时在native 层做设备检查, xposed 对这一层的操作无能为力。或者通过设备属性获取,xposed也是没有办法修改。检测不同方式获取设备信息的一致性,凭此一点便可判断是否修改设备。如此不完整的修改还不如不改。
大型公司和专业的检测工具公司,专门一群人天天研究怎么反作弊,反伪装,你懂的他们更精通。是否有办法完美伪装和改机呢,理论上有,因为设备在自己手中。
————————————————
看文这篇博文你对其他改机技术有兴趣可以看下这篇:手机无限制成为一台新设备
20-2第一篇:关于android对话框
public void showImagePickDialog() {
String title = "获取图片方式";
String[] choices = new String[]{"拍照", "从手机中选择"};
new AlertDialog.Builder( this)
.setTitle(title)
.setItems(choices, new DialogInterface.OnClickListener() {
.setNegativeButton("返回", null)
.show();
}
首先show出来消息对话框,其中有两个选项,拍照获取或者从手机相册
然后我们实现对点击事件进行监听
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
switch (which) {
case 0:
ImageUtils.openCameraImage(MainActivity.this);
break;
case 1:
ImageUtils.openLocalImage(MainActivity.this);
break;
}
}
当获取到点击事件后获取相应的方法,openCameraImage/openLocalImage;入伙时选择拍照我们要先确定内存情况,并且设置存储路径
private static Uri createImagePathUri(Context context) {
Uri imageFilePath = null;
String status = Environment.getExternalStorageState();
SimpleDateFormat timeFormatter = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA);
long time = System.currentTimeMillis();
String imageName = timeFormatter.format(new Date(time));
ContentValues values = new ContentValues(3);
values.put(MediaStore.Images.Media.DISPLAY_NAME, imageName);
values.put(MediaStore.Images.Media.DATE_TAKEN, time);
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
if (status.equals(Environment.MEDIA_MOUNTED)) {// 判断是否有SD卡,优先使用SD卡存储,当没有SD卡时使用手机存储
imageFilePath = context.getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} else {
imageFilePath = context.getContentResolver().insert(
MediaStore.Images.Media.INTERNAL_CONTENT_URI, values);
}
Log.i("", "生成的照片输出路径:" + imageFilePath.toString());
return imageFilePath;
}
}
public static void openCameraImage(final Activity activity) {
ImageUtils.imageUriFromCamera = ImageUtils.createImagePathUri(activity);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, ImageUtils.imageUriFromCamera);
activity.startActivityForResult(intent, ImageUtils.GET_IMAGE_BY_CAMERA);
}
MediaStore.EXTRA_OUTPUT参数不设置时,系统会自动生成一个uri,但是只会返回一个缩略图
在onActivityResult中获取图片数据。
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_CANCELED) {
return;
}
switch (requestCode) {
case ImageUtils.GET_IMAGE_BY_CAMERA:
if(ImageUtils.imageUriFromCamera != null) {
ImageUtils.cropImage(this, ImageUtils.imageUriFromCamera);
break;
}
break;
拍照获取图片并且自定义Uri(ImageUtils.imageUriFromCamera),用于保存拍照后图片地址,最后通过cropImage进行裁剪;
1.宽高和比例都不设置时,裁剪框可以自行调整(比例和大小都可以随意调整)
2.只设置裁剪框宽高比(aspect)后,裁剪框比例固定不可调整,只能调整大小
3.裁剪后生成图片宽高(output)的设置和裁剪框无关,只决定最终生成图片大小
4.裁剪框宽高比例(aspect)可以和裁剪后生成图片比例(output)不同,此时,
public static void cropImage(Activity activity, Uri srcUri) {
ImageUtils.cropImageUri = ImageUtils.createImagePathUri(activity);
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(srcUri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra(MediaStore.EXTRA_OUTPUT, ImageUtils.cropImageUri);
intent.putExtra("return-data", false);
activity.startActivityForResult(intent, CROP_IMAGE);
}
最后是全部代码
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);
findViewById(R.id.btn).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
showImagePickDialog();
}
});
}
public void showImagePickDialog() {
String title = "获取图片方式";
String[] choices = new String[]{"拍照", "从手机中选择"};
new AlertDialog.Builder( this)
.setTitle(title)
.setItems(choices, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
switch (which) {
case 0:
ImageUtils.openCameraImage(MainActivity.this);
break;
case 1:
ImageUtils.openLocalImage(MainActivity.this);
break;
}
}
})
.setNegativeButton("返回", null)
.show();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_CANCELED) {
return;
}
switch (requestCode) {
case ImageUtils.GET_IMAGE_BY_CAMERA:
if(ImageUtils.imageUriFromCamera != null) {
ImageUtils.cropImage(this, ImageUtils.imageUriFromCamera);
break;
}
break;
case ImageUtils.GET_IMAGE_FROM_PHONE:
if(data != null && data.getData() != null) {
ImageUtils.cropImage(this, data.getData());
}
break;
case ImageUtils.CROP_IMAGE:
if(ImageUtils.cropImageUri != null) {
iv.setImageURI(ImageUtils.cropImageUri);
}
break;
default:
break;
}
}
}
第二部分
public class ImageUtils {
public static final int GET_IMAGE_BY_CAMERA = 5001;
public static final int GET_IMAGE_FROM_PHONE = 5002;
public static final int CROP_IMAGE = 5003;
public static Uri imageUriFromCamera;
public static Uri cropImageUri;
public static void openCameraImage(final Activity activity) {
ImageUtils.imageUriFromCamera = ImageUtils.createImagePathUri(activity);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, ImageUtils.imageUriFromCamera);
activity.startActivityForResult(intent, ImageUtils.GET_IMAGE_BY_CAMERA);
}
public static void openLocalImage(final Activity activity) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
activity.startActivityForResult(intent, ImageUtils.GET_IMAGE_FROM_PHONE);
}
public static void cropImage(Activity activity, Uri srcUri) {
ImageUtils.cropImageUri = ImageUtils.createImagePathUri(activity);
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(srcUri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra(MediaStore.EXTRA_OUTPUT, ImageUtils.cropImageUri);
intent.putExtra("return-data", false);
activity.startActivityForResult(intent, CROP_IMAGE);
}
private static Uri createImagePathUri(Context context) {
Uri imageFilePath = null;
String status = Environment.getExternalStorageState();
SimpleDateFormat timeFormatter = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA);
long time = System.currentTimeMillis();
String imageName = timeFormatter.format(new Date(time));
ContentValues values = new ContentValues(3);
values.put(MediaStore.Images.Media.DISPLAY_NAME, imageName);
values.put(MediaStore.Images.Media.DATE_TAKEN, time);
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
if (status.equals(Environment.MEDIA_MOUNTED)) {// 判断是否有SD卡,优先使用SD卡存储,当没有SD卡时使用手机存储
imageFilePath = context.getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} else {
imageFilePath = context.getContentResolver().insert(
MediaStore.Images.Media.INTERNAL_CONTENT_URI, values);
}
Log.i("", "生成的照片输出路径:" + imageFilePath.toString());
return imageFilePath;
}
}
布局页面,只有两个view,简单的写了一下,仅供参考
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
android:background="@android:color/white"
tools:context=".MainActivity" >
<Button
android:id="@+id/btn"
android:text="获取照片"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
<ImageView
android:id="@+id/iv"
android:background="@android:color/black"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
</LinearLayout>
Android 11 安装EdXposed + Magisk框架
一. miui解bl锁
1.1.1 官网(http://www.miui.com/unlock/index.html)下载官方解锁工具,并解压
1.1.2.打开miflash_unlock
1.1.3 登录小米账号,自行bl解锁(这个很简单),注意解锁并没有root
二. 下载工具
2.1 Magisk下载及安装
Magisk下载https://github.com/topjohnwu/Magisk/releases
apk在已经解锁的手机上进行安装
2.2 使用Magisk获取root权限
先在官网下载手机系统对应的刷机包
解压打开后找到boot.img,放入手机文件夹下
手机打开Magisk,点击安装 ->选择并修补一个文件
找到boot.img, magisk会重新生成一个.img文件
在文件夹中找到生成的.img文件,并记住文件名
然后cmd执行如下命令:
//进入fastboot模式
adb reboot bootloader
//将magisk_patched_gpHO2.img刷入手机
fastboot flash boot magisk_patched_gpHO2.img
//刷入完成后手机进行重启
fastboot reboot
目前root完成,magisk应该就已经安装成功了。
2.3 EdXposed下载及安装
在 Magisk的插件中找到riru和ruri-edxpoded,并安装
安装过程比较简单这里就跳过
模块可以自行下载哦
参考:
https://blog.csdn.net/Aaron_Miller/article/details/106958610
Android 7.0及其以上系统拍照,打开相册,裁剪,报错: android.os.FileUriExposedException
在Android7.0的系统上调用系统相机拍照或者进相册选择图片时,会报如下错误: android.os.FileUriExposedException: ******** exposed beyond app through Intent.getData()
产生原因
其实不仅是调用相机和相册,只要是访问文件,都会出现这个错误,其原因是Android 7.0 做了一些系统权限更改,为了提高私有文件的安全性,面向 Android 7.0 或更高版本的应用私有目录被限制访问,此设置可防止私有文件的元数据泄漏,如它们的大小或存在性。而此权限更改有多重副作用,其中之一就是当传递软件包网域外的 file:// URI 可能给接收器留下无法访问的路径。因此,尝试传递 file:// URI 会触发 FileUriExposedException。分享私有文件内容的推荐方法是使用 FileProvider。在应用间共享文件 对于面向 Android 7.0 的应用,Android 框架执行的 StrictMode API 政策禁止在您的应用外部公开 file:// URI。如果一项包含文件 URI 的 intent 离开您的应用,则应用出现故障,并出现 FileUriExposedException 异常。要在应用间共享文件,应发送一项 content:// URI,并授予 URI 临时访问权限。进行此授权的最简单方式是使用 FileProvider 类。
解决办法
官方的解决办法Setting Up File Sharing
第一步:在AndroidManifest中配置:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="{程序包名}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
说明:android:authorities="{程序包名}.provider" 这个值可以随便写。我用的是程序包名。这个值决定了fileProVider生成的uri的路径。后面详细介绍
exported:要求必须为false,为true则会报安全异常。grantUriPermissions:true,表示授予 URI 临时访问权限。
第二步:res目录下新建一个xml文件夹,然后新建文件provider_paths.xml(同配置文件中的resource值一致),其内容为
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="files_root" path="Android/data/{包名}/"/>
<external-path name="external_storage_root" path="."/>
</paths>
第三部程序中使用:
Uri takePhotoUri;
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String takePhotoPath = Tools.getSDPath(Constants.ImageCameraPath)+ Tools.getPhotoFileName();// 拍照后的照片路径(自己设置)
File file = new File(takePhotoPath);//创建图片文件
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
takePhotoUri = FileProvider.getUriForFile(this, getPackageName() +".provider", file);
} else {
takePhotoUri= Uri.fromFile(file);
}
intent.putExtra(MediaStore.EXTRA_OUTPUT, takePhotoUri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
startActivityForResult(intent, CAMERA_WITH_DATA);
说明:FileProvider.getUriForFile();方法中的第二个参数要跟配置文件中的android:authorities值相对应。
第四步,获取拍照完成后的图片
在 onActivityResult()方法中使用data.getData();方法来获取 Uri实际是行不通的,可以在第三步的时候把拍照后的照片路径takePhotoPath设为一个全局变量
这样的话就可以直接使用这个路径来获取拍照后的图片。
String crop_image = new SimpleDateFormat("yyyy_MMdd_hhmmss").format(new Date()) + "_crop" + ".jpg";//剪切后的图片
File cropFile = createFile(crop_image); File file = new File(takePhotoPath);//直接使用第三步设置的路径来获取拍照后的图片
Uri imageUri;
Uri cropUri;
Intent intent = new Intent("com.android.camera.action.CROP");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
imageUri = FileProvider.getUriForFile(this, getPackageName() +".provider", file); cropUri = Uri.fromFile(cropFile);
} else {
imageUri = Uri.fromFile(file); cropUri = Uri.fromFile(cropFile);
}
intent.setDataAndType(imageUri, "image/*");
intent.putExtra("crop", "true"); //设置宽高比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1); //设置裁剪图片宽高
intent.putExtra("outputX", 400);
intent.putExtra("outputY", 400);
intent.putExtra("scale", true); //裁剪成功以后保存的位置
intent.putExtra(MediaStore.EXTRA_OUTPUT, cropUri);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true); startActivityForResult(intent, CROP_RESULT_CODE);
Android android:exported = true 用法详解
Android相关属性的介绍:android:exported = true
- 在Activity中该属性用来标示:当前Activity是否可以被另一个Application的组件启动:true允许被启动;false不允许被启动。
- android:exported 是Android中的四大组件 Activity,Service,Provider,Receiver 四大组件中都会有的一个属性。
- 总体来说它的主要作用是:是否支持其它应用调用当前组件。
例如:
<activity android:exported="true" …/>
注意:
AndroidManifest中android:exported="false"
如果Service等的AndroidManifest中声明为android:exported="false"
则该服务不能够跨进程使用。
Permission Denied!
需要改为:android:exported="true"
以上就是本次介绍的全部知识点内容,感谢大家的阅读和对我们的支持。
关于转载:关于android 一键新机,改机概述 xposed 改机优缺点和android改机系列的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于20-2第一篇:关于android对话框、Android 11 安装EdXposed + Magisk框架、Android 7.0及其以上系统拍照,打开相册,裁剪,报错: android.os.FileUriExposedException、Android android:exported = true 用法详解等相关内容,可以在本站寻找。
本文标签: