2022-03-21
3084
继续折腾Usb手机共享网络,以前是用的电池,很快鼓包了,换成18650限制充电量后,还是只能用一阵子就会莫名关机.最后选择使用5v直接接电池保护板,直流供电.但是有一个问题就是断电后不会自动启动,下面介绍通过修改boot完成关机充电时自动开机.完成自动开机后,安装tasker为系统应用,实现开机自动启动我们的应用实现usb连接自动启用usb共享.以下内容转自:https://zhuanlan.zhihu.com/p/418262993?ivk_sa=1024320u目的需求:在手机关机状态下,若是通电,则自动开机.使用场景:手机做4G路由器热点使用;备用手机常年通电做转发短信未接来电;做车载导航行车记录仪等;方法思路:确定手机关机状态下充电时会调用什么脚本命令,然后在脚本命令中添加入重启指令。步骤预览:提取手机boot.img镜像解包boot.img镜像修改init.rc文本打包boot.img刷入修改后的boot.img到手机完成,测试实践环境:手机: Redmi Note5; Android 版本 9; MIUI 版本10 9.9.3开发版;电脑: windows10工具: ADB, Fastboot, Bootimg[工具下载:把你的旧手机改造成车载导航.zip]1. 提取手机boot.img镜像1.1. 手机打开USB调试(开发者选项)1.2. 手机USB连接电脑1.3. 在CMD窗口cd到adb.exe的路径,输入“adb devices”来检测一下链接状况。C:\platform-toolsadb devicesList of devices attached63d76abf device #连接成功1.4. 输入“adb shell”,回车,再输入“su”回车,这注意看,提示符应该已经从$符号变成了#号。1.5. 输入命令搜索”find /dev/block/platform/ -name by-name”来找到”by-name”文件夹路径2|:/dev # find /dev/block/platform/ -name by-namefind /dev/block/platform/ -name by-namefind /dev/block/platform/ -name by-name/dev/block/platform/soc/c0c4000.sdhci/by-name //找到需要的路径1.6. 输入命令列出搜索到的文件夹”ls -al /dev/block/platform/soc/c0c4000.sdhci/by-name”,找到boot对应文件名称为”mmcblk0p58”ls -al /dev/block/platform/soc/c0c4000.sdhci/by-nametotal 0drwxr-xr-x 2 root root 1320 1970-01-01 08:02 .drwxr-xr-x 3 root root 1380 1970-01-01 08:02 ..lrwxrwxrwx 1 root root 21 1970-01-01 08:02 abl - /dev/block/mmcblk0p25lrwxrwxrwx 1 root root 21 1970-01-01 08:02 ablbak - /dev/block/mmcblk0p26lrwxrwxrwx 1 root root 21 1970-01-01 08:02 apdp - /dev/block/mmcblk0p11lrwxrwxrwx 1 root root 21 1970-01-01 08:02 bk1 - /dev/block/mmcblk0p49lrwxrwxrwx 1 root root 21 1970-01-01 08:02 bk2 - /dev/block/mmcblk0p51lrwxrwxrwx 1 root root 21 1970-01-01 08:02 bluetooth - /dev/block/mmcblk0p38lrwxrwxrwx 1 root root 21 1970-01-01 08:02 boot - /dev/block/mmcblk0p58 //找到boot对应的文件名"mmcblk0p58"1.7. 开始提取,输入“dd if=/dev/block/mmcblk0p58 of=/sdcard/boot.img”,这里的”mmcblk0p58”就是刚才上面找到的boot对应文件.1.8. 把提取的”boot.img”文件拷贝到电脑2. 解包boot.img镜像2.1. 电脑上把拷贝的boot.img和bootimg.exe放在相同目录下。最好单独建个目录,把这两个文件放进去,因为后续会产生很多文件,以免混乱。2.2 . CMD到bootimg.exe目录下执行“bootimg —unpack-bootimg” 解包 //路径不能有中文.否则报错C:\platform-tools\bootimgbootimg --unpack-bootimgarguments: [bootimg file]bootimg file: boot.imgoutput: kernel[.gz] ramdisk[.gz] second[.gz]base: 0x0ramdisk_addr: 0x1000000second_addr: 0xf00000tags_addr: 0x100page_size: 4096name: ""cmdline: "console=ttyMSM0,115200,n8 androidboot.console=ttyMSM0 earlycon=msm_serial_dm,0xc170000 androidboot.hardware=qcom user_debug=31 msm_rtb.filter=0x37 ehci-hcd.park=3 lpm_levels.sleep_disabled=1 sched_enable_hmp=1 sched_enable_power_aware=1 service_locator.enable=1 swiotlb=1 firmware_class.path=/vendor/firmware_mnt/image loop.max_part=7 buildvariant=user"padding_size=4096arguments: [ramdisk file] [directory]ramdisk file: ramdisk.gzdirectory: initrdoutput: cpiolist.txtcompress: True3. 修改init.rc文本3.1. 解包boot.img后会获得”initrd”文件夹,里面有我们需要修改的”init.rc”文件3.2. 使用EmEditor修改init.rc文件,在”on charger”这一项目添加”setprop sys.powerctl reboot”on charger class_start charger #这段自带不用删也可以,而且听说某些系统需要先进入charger流程,否则会卡第一屏 setprop sys.powerctl reboot #添加进这段3.3. 修改init.rc完毕,保存.4. 打包boot.img4.1. 现在要把修改的文件重新打包成boot.img。还是回到刚才的cmd窗口。输入“bootimg --repack-bootimg”回车。程序会自动把文件打包回去。现在目录下就会变成3个文件,一个程序bootimg.exe,一个原始文件boot-old.img,一个新生成的文件boot-new.img。5. 刷入修改后的boot.img到手机5.1. 把boot-new.img拷贝到adb.exe所在的目录,并且重命名为boot.img,在此目录打开命令窗口。5.2. 把手机进入到fastboot的状态。关机,同时按住音量减和电源键。这时你的手机会进入fastboot的状态,准备开始写入boot.img。5.3. 在命令窗口输入“fastboot flash boot boot.img”回车,开始刷写boot.img。因为文件很小,几秒钟就提示完成了。5.4. 输入“fastboot reboot”回车,会重启手机6. 完成,测试6.1 操作完以上步骤,就实现了安卓关机状态通电自动开机.6.2 测试1: 关机,保持usb线供电,数秒后自动开机.6.3 测试2: 关机.拔掉usb线,然后插入usb线,数秒后自动开机.完成.参考资料安卓6.0+关机状态下通电自动开机方案把你的旧手机改造成车载导航车子点火手机自动开机(关机状态下)的方法
继续阅读»
2019-09-27
1064
最近做一个Android课的项目后台返回json如下:{"success":true,"code":"200","msg":"查询成功","data":[{"id":1,"title":"新闻1","content":"内容1","author":1,"category":0,"status":1,"createTime":1449504000000,"updateTime":null},{"id":2,"title":"新闻2","content":"内容2","author":1,"category":0,"status":1,"createTime":1449504000000,"updateTime":null}]}我的做法是,直接将后台返回的实体类直接拷贝到Android项目中:public class ResponseWrapper { /** * 是否成功 */ private boolean success; /** * 返回码 */ private String code; /** * 返回信息 */ private String msg; /** * 返回数据 */ private Object data;}然后正常okhttp请求:OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url(IpAddress.SERVER_IP+"/news/all").build();Call call = client.newCall(request);call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { ResponseWrapper responseWrapper = new Gson().fromJson(response.body().string(),ResponseWrapper.class); newsList = (ListNews) responseWrapper.getData(); Message message = handler.obtainMessage(); handler.sendMessage(message); }});然后报错java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to team.mywzll.onenews.entity.News研究了许久,发现需要给返回的实体类也就是ResponseWrapper添加范型,不能是Object类型,然后修改成如下:public class ResponseWrapperT { private boolean success; private String code; private String msg; private T data;}添加了范型后,对应的string转对象也需要修改:ResponseWrapper responseWrapper = new Gson().fromJson(response.body().string(),new TypeTokenResponseWrapperListNews(){}.getType());再次运行:com.google.gson.JsonSyntaxException: 1449504000000... Caused by: java.text.ParseException: Failed to parse date ["1449504000000"]: Invalid time zone indicator '0'... Caused by: java.lang.IndexOutOfBoundsException: Invalid time zone indicator '0'面临崩溃,又百度许久,发现是由于返回的对象中存在date类型的字段, 需要这样,具体为什么我也不明白:builder.registerTypeAdapter(Date.class, new JsonDeserializerDate() { public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { return new Date(json.getAsJsonPrimitive().getAsLong()); }});Gson gson = builder.create();ResponseWrapper responseWrapper = gson.fromJson(rep,new TypeTokenResponseWrapperListNews(){}.getType());这时候解析终于正常了,于是我又想用更装逼的retrofit进行网络请求:public interface NewsInterface { @GET("/news/all") CallResponseWrapper getAllNews();}Retrofit retrofit = RetrofitUtils.getInstance();NewsInterface newsInterface = retrofit.create(NewsInterface.class);newsInterface.getAllNews().enqueue(new CallbackResponseWrapper() { @Override public void onResponse(CallResponseWrapper call, ResponseResponseWrapper response) { ResponseWrapper responseWrapper = response.body(); newsList = (ListNews) responseWrapper.getData(); HomeListAdapter adapter = new HomeListAdapter(getContext(),newsList); homeListView.setAdapter(adapter); } @Override public void onFailure(CallResponseWrapper call, Throwable t) { t.printStackTrace(); }});还是上面第一个错误一样无法将com.google.gson.internal.LinkedTreeMap转为我的news实体类然后百度,试了好几次都不行,然后看见一个stackoverflow的提问:https://stackoverflow.com/questions/46296747/com-google-gson-internal-linkedtreemap-cannot-be-cast的采纳答案:[图片]意思是retrofit请求接口返回值没有指定范型,于是我修改:public interface NewsInterface { @GET("/news/all") CallResponseWrapperListNews getAllNews(); }然后再试就又报之前那个json语法错误,还是date类型变量的问题,试了一下,可以把实体类date类型改成string勉强解决,但那样太low了还是苦苦的查资料,发现可以在retrofit中添加gson对象,于是我还是用了上面的GsonBuilder的方法,把生成的gson对象传给retrofit:public class RetrofitUtils { private static Retrofit mInstance; private static Gson gson; static { GsonBuilder builder = new GsonBuilder(); // Register an adapter to manage the date types as long values builder.registerTypeAdapter(Date.class, new JsonDeserializerDate() { public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { return new Date(json.getAsJsonPrimitive().getAsLong()); } }); gson = builder.create(); } public static Retrofit getInstance(){ if (mInstance ==null){ synchronized (RetrofitUtils.class){ if (mInstance ==null){ mInstance = new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create(gson)).baseUrl(IpAddress.SERVER_IP).build(); } } } return mInstance; }}最后问题终于解决!总结:如果服务端要统一返回接口而封装返回类型,那么在Android端进行解析时要明确指定返回数据的具体类型,例如我这里返回json的data字段为一个ListNews因此不能照搬服务端的返回实体类,需要添加范型,并在使用gson进行解析时指定范型,目前我只知道 new TypeTokenResponseWrapperListNews(){}.getType(), 这种方法如果使用retrofit的话只需在api接口对应方法的返回值指定范型即可出现类型转换失败的原因应该就是stackoverflow上回答的一样:due to the missing type information ,gsonis returning aListof internally created objectsLinkedTreeMapand since you are usingrawtypes (should be a warning for unchecked cast)with declaration as concrete type which will create a issue when adapter actually expecting aPojoObjectbut internally it's something else.由于缺失数据的类型信息,Gson返回了一个内部的LinkedTreeMap,导致后续使用时报错
继续阅读»
2019-05-15
718
//设置状态栏文字颜色及图标为浅色(默认即为浅色,网上找了很久)getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);//设置状态栏文字颜色及图标为深色getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
继续阅读»
2019-05-10
717
1. RadioButton采用 "android:drawableTop"设置两种状态的图标时无效:错误写法:[图片]修改为这样就正常了:[图片]2.自定义ToolBar时左边始终有类似padding效果:[图片]只要在Toolbar添加以下属性即可:app:contentInsetStart="0dp"这样:[图片]
继续阅读»