第一份工作中的部分笔记
不知不觉中,我也到了可以带新人的时候了,有必要整理一下自己的知识,发几篇文章看看了。
这些笔记都是从oneNote抄来的,记录了当时实际水平,由于ONENOTE不支持对应格式,部分代码需要手动加空格。
单一职责原则
image.png开闭原则
image.png软件中的对象(类,接口,函数),对于扩展是开放的,对于修改是封闭的。
使得系统增加新功能时,只需添加,减少修改。
里氏替换原则
image.png使用父类的地方都可以使用子类,反过来不一定。使用者可能不需要知道是父类还是子类。
解决"No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android"错误
实际上就是NDK不兼容旧版builder.gradle(3.0及以前版本),修改builder.gradle到3.2.0,解决这个,算是解决了一半,剩下的修改到gradle-4.6-all.zip,在gradleWrapper里面。再刷新项目,就好了。大概是这样,好像还安装了28.0.2buildTool。反正是as提示的,点一下自动安装了。
Error:All flavors must now belong to a named flavor dimension. Learn more at
使用了productFlavors分包,解决方法就是在build.gradle中的defaultConfig中添加一个flavorDimensions "1"就可以了,后面的1一般是跟你的versionCode相同
failed: Connection refused: connect 的解决办法
在如下图所示的路径下的这个文件用文本编辑器打开后,删除代理相关的设置代码就好了。
image.png
自动生成debug文件名
android.applicationVariants.all{
variant->
variant.outputs.all{
//这里修改apk文件名
outputFileName="SystemClockAndRTCClockShowing_${variant.versionName}_for8.1.apk"
}
}
applicationVariants.all{variant->
variant.outputs.all{
deffileName="Mlock_v${variant.versionName}_${variant.buildType.name}.apk"
outputFileName=fileName
}
}
applicationVariants.all{variant->
variant.outputs.all{
deffileName="AndroidStressTest_${variant.buildType.name}_v${variant.versionName}_${releaseTime()}.apk"
outputFileName=fileName
}
}
https://github.com/aystshen/AndroidStressTest在这个项目里的配置
下面的不能用
applicationVariants.all {
variant ->
variant.outputs.each {
output ->
def outputFile = output.outputFile
def fileName
if (outputFile != null && outputFile.name.endsWith('.apk')) {
if (variant.buildType.name.equals('release')) {
fileName = "XXX_v${defaultConfig.versionName}.apk"
} else if (variant.buildType.name.equals('debug')) {
fileName = "XXX_v${defaultConfig.versionName}_debug.apk"
}
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
3.4.0 Failure [INSTALL_FAILED_SHARED_USER_INCOMPATIBLE]
居然升级implementation'com.android.support:support-v4:26.0.0-alpha1'
这些解决了,项目结构里编译器建议的
Lint found fatal errors while assembling a release target.
lintOptions {
checkReleaseBuilds false
// Or, if you prefer, you can continue to check for errors in release builds,
// but continue the build even when errors are found:
abortOnError false
}
控制Release和debug的log问题
添加到
debug{
signingConfigsigningConfigs.k44
buildConfigField"boolean","LOG","true"
}
rebuild后加入
publicstaticfinalbooleanDEBUG=BuildConfig.LOG;
最后设置个
publicstaticvoidlogD(StringclassTAG,Stringmsg){
if(DEBUG){
Log.d("EthernetWatchService",classTAG+msg);
}
}
publicstaticvoidlogE(StringclassTAG,Stringmsg){
if(DEBUG){
Log.e("EthernetWatchService",classTAG+msg);
}
}
TextView
滚动
textView.setMovementMethod(ScrollingMovementMethod.getInstance());
回到第一行
textView.scrollTo(0,0);
末尾添加文字
textView.append("_");
重置文字为
textView.setText("_");
Button继承TextView,让我有点意外。TextView继承View。
动画
实现方式
<?xmlversion="1.0"encoding="utf-8"?>
<animation-listxmlns:android="http://schemas.android.com/apk/res/android">
<itemandroid:drawable="@drawable/run0"android:duration="150"/>
<itemandroid:drawable="@drawable/run1"android:duration="150"/>
<itemandroid:drawable="@drawable/run2"android:duration="150"/>
<itemandroid:drawable="@drawable/run3"android:duration="150"/>
<itemandroid:drawable="@drawable/run4"android:duration="150"/>
<itemandroid:drawable="@drawable/run5"android:duration="150"/>
<itemandroid:drawable="@drawable/run6"android:duration="150"/>
</animation-list>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val text:ImageView=findViewById(R.id.text_view)
if(Build.VERSION.SDK_INT>21){
text.setImageDrawable(getDrawable(R.drawable.animation))
val animation:AnimationDrawable =text.drawable as AnimationDrawable
animation.start()
}
}
https://blog.csdn.net/wanmeilang123/article/details/53929484
优化流程,先放一下
生成系统签名
https://pan.baidu.com/s/1kVmXVKV
需要openssl文件,以上链接有提供该文件的下载
1.android 源码目录build\target\product\security 取platform.pk8 platform.x509.pem放到一个目录下
将cmd控制台切换到该目录,分别执行以下命令即可:
2 //生成shared.priv.pem;
openssl pkcs8 -in platform.pk8 -inform DER -outform PEM -out shared.priv.pem -nocrypt
3 //生成pkcs12;
openssl pkcs12 -export -in platform.x509.pem -inkey shared.priv.pem -out shared.pk12 -name androiddebugkey
Enter Export Password: (输入密码android,默认是android,如是自己制作的key,输入对应的密码)
Verifying - Enter Export Password:(输入密码android)
4 生成debug.keystore
keytool -importkeystore -deststorepass android -destkeypass android -destkeystore debug.keystore -srckeystore shared.pk12 -srcstoretype PKCS12 -srcstorepass android -alias androiddebugkey
来自 https://blog.csdn.net/sinat_21468979/article/details/78780655
获取外置sd卡路径
https://blog.csdn.net/csd_meb/article/details/72870319
完全看不懂
privatestaticStringgetStoragePath(ContextmContext,booleanis_removale){
StorageManagermStorageManager=(StorageManager)mContext.getSystemService(Context.STORAGE_SERVICE);
Class<?>storageVolumeClazz=null;
try{
storageVolumeClazz=Class.forName("android.os.storage.StorageVolume");
MethodgetVolumeList=mStorageManager.getClass().getMethod("getVolumeList");
MethodgetPath=storageVolumeClazz.getMethod("getPath");
MethodisRemovable=storageVolumeClazz.getMethod("isRemovable");
Objectresult=getVolumeList.invoke(mStorageManager);
finalintlength=Array.getLength(result);
for(inti=0;i<length;i++){
ObjectstorageVolumeElement=Array.get(result,i);
Stringpath=(String)getPath.invoke(storageVolumeElement);
booleanremovable=(Boolean)isRemovable.invoke(storageVolumeElement);
if(is_removale==removable){
returnpath;
}
}
}catch(ClassNotFoundExceptione){
e.printStackTrace();
}catch(InvocationTargetExceptione){
e.printStackTrace();
}catch(NoSuchMethodExceptione){
e.printStackTrace();
}catch(IllegalAccessExceptione){
e.printStackTrace();
}
returnnull;
}
WebView
这个控件还是要好好学一下
具体使用的流程,是个大坑。
添加以下代码,解决
android.view.InflateException: Binary XML file line #8: Binary XML file line #8: Error inflating class android.webkit.WebView
publicstaticvoidhookWebView(){
intsdkInt=Build.VERSION.SDK_INT;
try{
Class<?>factoryClass=Class.forName("android.webkit.WebViewFactory");
Fieldfield=factoryClass.getDeclaredField("sProviderInstance");
field.setAccessible(true);
ObjectsProviderInstance=field.get(null);
if(sProviderInstance!=null){
//log.debug("sProviderInstanceisn'tnull");
System.out.println("sProviderInstanceisn'tnull");
return;
}
MethodgetProviderClassMethod;
if(sdkInt>22){
getProviderClassMethod=factoryClass.getDeclaredMethod("getProviderClass");
}elseif(sdkInt==22){
getProviderClassMethod=factoryClass.getDeclaredMethod("getFactoryClass");
}else{
//log.info("Don'tneedtoHookWebView");
System.out.println("Don'tneedtoHookWebView");
return;
}
getProviderClassMethod.setAccessible(true);
Class<?>providerClass=(Class<?>)getProviderClassMethod.invoke(factoryClass);
Class<?>delegateClass=Class.forName("android.webkit.WebViewDelegate");
Constructor<?>providerConstructor=providerClass.getConstructor(delegateClass);
if(providerConstructor!=null){
providerConstructor.setAccessible(true);
Constructor<?>declaredConstructor=delegateClass.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
sProviderInstance=providerConstructor.newInstance(declaredConstructor.newInstance());
//log.debug("sProviderInstance:{}",sProviderInstance);
System.out.println("sProviderInstance");
field.set("sProviderInstance",sProviderInstance);
}
//log.debug("Hookdone!");
System.out.println("Hookdone!");
}catch(Throwablee){
//log.error(e);
System.out.println(e);
}
}
handler消息机制
image.pngMessage:消息。包含消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
Handler:处理者,负责Message的发送及处理。使用Handlee时,需要实现handleMessage(Message msg)方法对特定的Message进行处理,例如更新UI等。
MessageQueue:消息队列,用来存放Handlee发送过来的消息,并按照FIFPO规则执行。并非是实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取
Looper:消息泵,不断地从MessageQueue中抽取Message执行。一个MessageQueue需要一个Looper
Thread:线程,负责调度整个消息循环,即消息循环的执行场所。
子线程更新UI
1.主线程定义Handle
主线程:
Handler mHandler=new Handler(){
@override
public void handleMessage(Message msg){
super.handleMessage(msg);
switch(msg.what){
case 0:
string data=(String) msg.obj;
updataWeather();
textView.setText(data);
break;
default:
break;
}
}
}
子线程:
private void updataWeather(){
New Thread(new Runnable(){
@override
public void run(){
//耗时操作,完成后发送消息给handler,完成UI更新
mHandler.sendEmptyMessage(0);
//需要数据传递,用下面的方法
Message msg=new Message();
}
}).start();
}
如果多个类直接相互调用,就不方便,需要传递content对象,或通过接口调用。
2用Activity对象的runOnUiThread方法更新
在子线程中通过runOnUiThread()方法更新UI
new Thread(){
public void run(){
//耗时操作,完成后价值UI
runOnThread(new Runable*(){\
@override
public void run(){
//更新UI
imageView.setImageBitmap(bitmap);
}
})};
}
}.start();
如果在非上下文类中,可以通过传递上下文实现调用。
Activity activity=(Activity) imageView.getContext();
Activity.runOnUiThread(new Runnable()){
@override
public void run(){
imageView.setImageBitmap(bitmap);
}
});
灵活,但是Thread定义在其他地方,需要传递Activity对象
View.post(Runnable r)
imageView.post(new Runnable(){
@override
public void run(){
imageView.setImageBitmap(bitmap);
}
});
方法简单,需要传递更新的View过去
UI更新必须在主线程中,所有方法都是将更新UI消息发送到主线程,让主线程做处理。
Broadcast Receiver
举例接收开机广播
开机广播好像是需要权限的,因为级别比较高。
1.首先声明权限
<uses-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
然后配置receiver属性
默认值为
<receiverandroid:name=".BootReceiver"
android:enabled="true"
android:exported="true">
</receiver>
为了加快启动速度,设置了优先级为最大整型数(据说是大流氓用的)
其次加入了要接受的广播,貌似是某个版本开始,需要显示声明了
<receiverandroid:name=".BootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter
android:priority="2147483647">
<actionandroid:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
2.再看java类
创建初如下
publicclassBootReceiverextendsBroadcastReceiver{
@Override
publicvoidonReceive(Contextcontext,Intentintent){
//TODO:ThismethodiscalledwhentheBroadcastReceiverisreceiving
//anIntentbroadcast.
}
thrownewUnsupportedOperationException("Notyetimplemented");
}
}
加入判断接收的广播名,做对应的动作,最后那个抛出异常,不知道为什么要加这个,我保留了
记得要加FLAG,因为是在activity之外启动activity,所以要加这个,原因为何?(这个涉及到activity task的问题)
publicclassBootReceiverextendsBroadcastReceiver{
@Override
publicvoidonReceive(Contextcontext,Intentintent){
//TODO:ThismethodiscalledwhentheBroadcastReceiverisreceiving
//anIntentbroadcast.
if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
Intentintent1=newIntent(context,MainActivity.class);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent1);
return;
}
thrownewUnsupportedOperationException("Notyetimplemented");
}
}
Selector
给控件添加选中以后的效果
selector_choose_food_activity_radio_button_rbleft.xml 放置drawable里面
<?xmlversion="1.0"encoding="utf-8"?>
<selectorxmlns:android="http://schemas.android.com/apk/res/android">
<itemandroid:state_enabled="true"android:state_focused="true"android:state_pressed="false"android:drawable="@mipmap/btn_entree_unchecked"/>
<itemandroid:state_enabled="true"android:state_pressed="true"android:drawable="@mipmap/btn_entree_checked"/>
<itemandroid:state_enabled="true"android:state_checked="true"android:drawable="@mipmap/btn_entree_checked"/>
<itemandroid:drawable="@mipmap/btn_entree_unchecked"/>
</selector>
之前一直出错
{order.zd.com.order/order.zd.com.order.activity.ChooseFoodActivity}: android.view.InflateException: Binary XML file line #38: Binary XML file line #38: Error inflating class android.widget.RadioButton
是因为我之前写的参考的button的写法,而项目实际使用的是RadioButton,这两种写法不一样,RadioButton要多一些选项
<itemandroid:state_checked="true"
anrdoid:drawable="@mipmap/btn_entree_checked"/>
<itemandroid:state_checked="false"
anrdoid:drawable="@mipmap/btn_entree_unchecked"/>
至于具体什么原因,还是未知的,还是要继续看看selector这东西到底怎么用
目标xml 放在layout里面
<RadioButton
android:id="@+id/rbleft"
android:layout_width="150px"
android:layout_height="150px"
android:layout_margin="0dp"
android:padding="0dp"
android:button="@null"
android:checked="true"
android:background="@drawable/selector_choose_food_activity_radio_button_rbleft"/>
android:button="@null"
消除按钮的圆圈
drawable替换LinearLayout背景
finalDrawabledrawable2=getResources().getDrawable(R.mipmap.bg_beverages);
chooseFoodLinearLayout.setBackground(drawable2);
动态设置控件宽度
ViewGroup.LayoutParamslayoutParams=pictureTwo.getLayoutParams();
layoutParams.height=0;
layoutParams.width=0;
pictureTwo.setLayoutParams(layoutParams);
picture.setLayoutParams(layoutParams);
官方文档
https://developer.android.google.cn/reference/android/support/v14/preference/PreferenceFragment.html
https://developer.android.google.cn/reference/packages
MultiSelectListPreference
multiSelecListPreferenceRepeat.setOnPreferenceChangeListener(newPreference.OnPreferenceChangeListener(){
@Override
publicbooleanonPreferenceChange(Preferencepreference,Objecto){
multiSelecListPreferenceRepeat.setSummary(o.toString());
returntrue;
}
});
provider还搞不懂
Failed to find provider info for com.z.settingnov7
开始还以为是url问题,后来才发现,是没有声明provider
<provider android:name="com.z.settingnov7.ClocksProvider"
android:authorities="com.z.settingnov7"
android:exported="false"/>
privatestaticfinalUriMatchersURLMatcher=newUriMatcher(
UriMatcher.NO_MATCH);
static{
sURLMatcher.addURI("com.z.settingnov7","clock",CLOCKS);
sURLMatcher.addURI("com.z.settingnov7","clock/#",CLOCKS_ID);
}
publicstaticfinalUriCONTENT_URI=Uri.parse("content://com.z.settingnov7/clock");
Cursorcursor=context.getContentResolver().query(
ContentUris.withAppendedId(Clock.Columns.CONTENT_URI,clockId),
Clock.Columns.CLOCK_QUERY_COLUMNS,null,null,null);
AlarmManager
bundle.putInt("clock_id",clock.id);
bundle.putString("ZndtimeString",(clock.hour+""+clock.minutes));
bundle.putLong("ZndtimeTarget",clock.time);
intentUpdateService.putExtras(bundle);
//ctx.startService(intentUpdateService);
Log.e(TAG,"sendUpdateBroadcast:设置调用service");
PendingIntentsender=PendingIntent.getService(ctx,0,intentUpdateService,PendingIntent.FLAG_CANCEL_CURRENT);
if(clock.id==4){
am.setExact(AlarmManager.RTC_WAKEUP,0,sender);
}else{
am.setExact(AlarmManager.RTC,0,sender);
}
am.set(AlarmManager.RTC,clock.time,sender);
}
退出应用
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);//正常退出
System.exit(1);//非正常退出
https://www.jianshu.com/p/1adb4a6b8618
有个很长的文章,没看完,有缘用到了再说
NdefRecord
Ndef:NFC Data Exchange Format
NdefRecord:一条记录包括四部分
3-bit TNF(Type Name Format):类型名称格式
完整封包
image.pngMifareClassic
byte[]readBlock(intblockIndex)
读取ic卡的一般步骤
获取NFCadapter实例
获取Tag实例
获取MifareClassic实例
调用连接方法
key认证,Android提供的有三种key,验证的是keya或keyb(有个demo只认证一种,被坑了,他也没说要认证)
调用readBlock读取
关闭连接
自己实现个二进制转十进制的方法
调用输出到表格
注意需要声明NFC权限
抓取log
adb shell logcat -v time > C:\Users\Administrator\Desktop\log.txt
adb shell dmesg > C:\Users\Administrator\Desktop\log2.txt
f分析log
https://blog.csdn.net/u011714701/article/details/53398447
编译报错
unfinished
Error:
崩溃
crash
闪退
Low_memory
ANR问题
Cmd
从按钮到文件
添加一个让所有红灯亮
1.按钮的监听事件里添加:
value();
ttyS=new SerialPort(newFile("/dev/ttyS1"),115200,0);//Openthebaudrate
UartSend.UartAllR(ttyS1,"ttyS1").run();
2.UartSend.java添加:
Public static Thread UartAllR(final SerialPort sp,final String name){
Retur nnew Thread(new Runnable(){
@Override
Public void run(){
if(LedActivity.lock==null){
System.out.println("lock=null");
}else{
try{
synchronized(LedActivity.lock){
out=sp.getFileOutputStream();
LampsUtil.AllRLamps();
out.close();
}
}catch(Exceptione){
e.printStackTrace();
}
}
}
});
}
3.LampsUtil里添加
publicstaticvoidAllRLamps()throwsIOException{//Alloftheredlight
UartSend.out.write(intToByteArray(num1));
UartSend.out.write(intToByteArray(num2));
for(inti=0;i<52;i++){
UartSend.out.write(intToByteArray(LedActivity.numL));
UartSend.out.write(intToByteArray(numB_off));
UartSend.out.write(intToByteArray(numR_Lamps));
UartSend.out.write(intToByteArray(numG_off));
}
UartSend.out.write(intToByteArray(num7));
}
不知道什么问题
Intentintent=newIntent("com.z.settingnov7.UpdateService");
startService(intent);
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.z.settingnov7/com.z.settingnov7.MainActivity}: java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.z.settingnov7.UpdateService }
改成
Intentintent=newIntent(this,UpdateService.class);
startService(intent);
Bundle bundle = new Bundle();
bundle.putInt("op", op);
intent.putExtras(bundle);
startService(intent);
BroadcastReceiver接收广播出错
thrownewUnsupportedOperationException("Notyetimplemented");
自动填充的代码,有个抛出异常,如果不删掉,会在收到系统广播的时候抛出异常
SystemClock.sleep(时间);
没有用Bundle传不过去,有了可以?
UpdateService
Intentintent1=newIntent(context,MainActivity.class);
Bundlebundle=newBundle();
bundle.putBoolean("start",true);
//intent.putExtra("start",true);
intent1.putExtras(bundle);
context.startActivity(intent1);
MainActivity
if(getIntent().getBooleanExtra("start",false)){
finish();
}
Error: null, Cannot fit requested classes in a single dex file (# methods: 101735 > 65536 ; # fields: 67215 > 65536)
判断wifi是否连接CONNECTED
ConnectivityManagermanager=(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo.Statewifi=manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState();
if(wifi==NetworkInfo.State.CONNECTED||wifi==NetworkInfo.State.CONNECTING){
Toast.makeText(this,"WIFIhadbeenCONNECTED!",Toast.LENGTH_SHORT).show();
finish();
}
判断wifi开关是否打开
WifiManagerwifiManager=(WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if(wifiManager.isWifiEnabled()){
Toast.makeText(this,"WIFIhadbeenEnabled!",Toast.LENGTH_SHORT).show();
finish();
}
https://www.jianshu.com/p/aaedd9aecbe4
Can't create handler inside thread that has not called Looper.prepare()
Looper.prepare();
ConnectivityManagerconn=(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
EthernetManagermEthernetManager=(EthernetManager)getSystemService("ethernet");
参考:
原子线程调用Toast报Can't create handler inside thread that has not called Looper.prepare() 错误
今天用子线程调Toast报了一个Can't create handler inside thread that has not calledLooper.prepare()错误。
解决方法
Looper.prepare();
Toast.makeText(getApplicationContext(), "test", Toast.LENGTH_LONG).show();
Looper.loop();
作者:No Silver Bullet
来源:CSDN
原文:https://blog.csdn.net/sunhuaqiang1/article/details/46839045
版权声明:本文为博主原创文章,转载请附上博文链接!
接收开机广播失败
我遇到的情况是没有UI
据说是android3.0以后就必须有一个ui界面,但实际我看不是这样的,手机里有很多没有UI的应用,也许是setting或者其他有UI的应用启动的
https://blog.csdn.net/baidu_27196493/article/details/78269674
androidstudio更改优先加载系统包framework.jar的顺序
有两种方法。
一种修改app.iml文件,临时性的,但直观
image.png
image.png
image.png
https://blog.csdn.net/hacker_crazy/article/details/78465959
添加cookie到webview
CookieManagercookieManager=CookieManager.getInstance();
cookieManager.setAcceptCookie(true);//允许接受Cookie
wifiWatchService?
EthernetManagermEthernetManager=(EthernetManager)getSystemService("ethernet");
在6.0 RK3288上报错
04-26 12:27:33.604 1364-1382/com.zd.wifiwatch E/AndroidRuntime: FATAL EXCEPTION: Thread-102
Process: com.zd.wifiwatch, PID: 1364
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)
at android.os.Handler.<init>(Handler.java:114)
at android.net.EthernetManager$1.<init>(EthernetManager.java:82)
at android.net.EthernetManager.<init>(EthernetManager.java:82)
at android.app.SystemServiceRegistry$47.createService(SystemServiceRegistry.java:528)
at android.app.SystemServiceRegistry$47.createService(SystemServiceRegistry.java:525)
at android.app.SystemServiceRegistry$CachedServiceFetcher.getService(SystemServiceRegistry.java:790)
at android.app.SystemServiceRegistry.getSystemService(SystemServiceRegistry.java:743)
at android.app.ContextImpl.getSystemService(ContextImpl.java:1365)
at android.content.ContextWrapper.getSystemService(ContextWrapper.java:627)
at com.zd.wifiwatch.WifiWatchService$2.run(WifiWatchService.java:277)
at com.zd.wifiwatch.WifiWatchService.resetWifi(WifiWatchService.java:321)
at com.zd.wifiwatch.WifiWatchService.access$1100(WifiWatchService.java:58)
at com.zd.wifiwatch.WifiWatchService$ResetThread.run(WifiWatchService.java:256)
网上的解决方法:
Looper.prepare();
EthernetManagermEthernetManager=(EthernetManager)getSystemService("ethernet");
Looper.loop();
但会引起另一个问题
01-01 09:56:48.955 F/DEBUG ( 227): Abort message: 'art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal start byte 0x80'
01-01 09:56:48.955 F/DEBUG ( 227): r0 00000000 r1 000004fd r2 00000006 r3 a1663978
01-01 09:56:48.955 F/DEBUG ( 227): r4 a1663980 r5 a1663930 r6 00000000 r7 0000010c
01-01 09:56:48.955 F/DEBUG ( 227): r8 b4d27378 r9 b7bc3c98 sl 00000001 fp 00000001
01-01 09:56:48.955 F/DEBUG ( 227): ip 00000006 sp a1660ba8 lr b6ce2ec9 pc b6ce52b8 cpsr 40070010
01-01 09:56:48.964 I/CalendarProvider2( 1319): Created com.android.providers.calendar.calendaralarmmanager@f9941bf(com.android.providers.calendar.calendarprovider2@f03608c)
01-01 09:56:48.968 F/DEBUG ( 227):
01-01 09:56:48.968 F/DEBUG ( 227): backtrace:
01-01 09:56:48.968 F/DEBUG ( 227): #00 pc 000442b8 /system/lib/libc.so (tgkill+12)
方法2:通过Looper.getMainLooper(),获得主线程的Looper,将其绑定到此Handler对象上。
final Runnable runnable = new Runnable() {
@Override
public void run() {
//执行耗时操作
try {
Log.e("bm", "runnable线程: " + Thread.currentThread().getId()+ " name:" + Thread.currentThread().getName());
Thread.sleep(2000);
Log.e("bm", "执行完耗时操作了~");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
new Thread() {
public void run() {
new Handler(Looper.getMainLooper()).post(runnable);//在子线程中直接去new 一个handler
//这种情况下,Runnable对象是运行在主线程中的,不可以进行联网操作,但是可以更新UI
}
}.start();
来自 https://www.cnblogs.com/jingmo0319/p/5730963.html
这个方法也一样
不知道什么原因,运行到某处停止了
if(DEBUG)Log.e(TAG,"onCreate:");
super.onCreate(savedInstanceState);
Intentintent=getIntent();
setValue=intent.getBooleanExtra("setting",false);
if(DEBUG)Log.i(TAG,"setting"+setValue);
if(DEBUG)Log.e(TAG,"onCreate:setValue");
super.enableCallMenu=false;
if(DEBUG)Log.e(TAG,"onCreate:enableCallMenu");
只有第一行的log
我把android studio invalidate以后,而且平板reset以后,好了
获取USB路径
public String getUSBHostName(Context context) {
StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
try {
Method getVolumeList = StorageManager.class.getDeclaredMethod("getVolumeList", null);
getVolumeList.setAccessible(true);
Class<?> classStorageVolume = Class.forName("android.os.storage.StorageVolume");
Method getPath = classStorageVolume.getDeclaredMethod("getPath", null);
Method getLabel = classStorageVolume.getDeclaredMethod("getUserLabel", null);
Object[] volumes = (Object[]) getVolumeList.invoke(storageManager, null);
Log.e(TAG, "detectUSBName: +++" + volumes);
if (volumes != null) {
for (int i = 0; i < volumes.length; i++) {
String path = (String) getPath.invoke(volumes[i], null);
String label = (String) getLabel.invoke(volumes[i], null);
if(label.equals("USB drive")){
Log.e(TAG, "detectUSBName Path:" + path + " Label:" + label);
return path;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
//throw new IllegalArgumentException("Can not find USB drive");
return "Can not find USB drive";
}
public String getSDCardHostName(Context context) {
StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
try {
Method getVolumeList = StorageManager.class.getDeclaredMethod("getVolumeList", null);
getVolumeList.setAccessible(true);
Class<?> classStorageVolume = Class.forName("android.os.storage.StorageVolume");
Method getPath = classStorageVolume.getDeclaredMethod("getPath", null);
Method getLabel = classStorageVolume.getDeclaredMethod("getUserLabel", null);
Object[] volumes = (Object[]) getVolumeList.invoke(storageManager, null);
Log.e(TAG, "detectUSBName: +++" + volumes);
if (volumes != null) {
for (int i = 0; i < volumes.length; i++) {
String path = (String) getPath.invoke(volumes[i], null);
String label = (String) getLabel.invoke(volumes[i], null);
if(DEBUG)Log.e(TAG, "getSDCardHostName: " +volumes[i]);
if(label.contains("card")||label.contains("sd")||label.contains("SDCard")){
if(DEBUG)Log.e(TAG, "getSDCardHostName Path:" + path + " Label:" + label);
return path;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
//throw new IllegalArgumentException("Can not find USB drive");
return "Can not find USB drive";
}
libxxx.so- text relocations问题的终极解决方案
https://blog.csdn.net/ahence/article/details/68953878
UART通信,使用22以上就报错
Adapter类持有activity引用
类似的应该还有webview和webviewClient
首先,Adapter类不能持有activity类的引用,之前没出问题,因为Adapter类里面没有做耗时操作,所以没有暴露问题。如果耗时长,会在activity被finish时,因被持有引用,而无法被回收。
不管是内部类,还是外部,只要持有引用都是一样的。
1.外部类
如果要和activity交互,传入一个context对象,那么,就建立了引用
public class ExampleAdapter extends BaseAdapter {
private Context mContext;
public ExampleAdapter(Context context) {
this.mContext = context;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
//这里也用到了activity的引用
convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item, null);
}
TextView textView = (TextView) convertView.findViewById(R.id.text);
textView.setText(String.valueOf(position));
Button button = (Button) convertView.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//使用构造方法传过来的上下文跳转界面
mContext.startActivity(new Intent(mContext, SecondActivity.class));
}
});
return convertView;
}
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.listView);
//这里将activity对象传入adapter
ExampleAdapter adapter = new ExampleAdapter(this);
listView.setAdapter(adapter);
}
}
解决方法,使用parent的context,写一个接口回调按钮监听方法
public class ExampleAdapter extends BaseAdapter {
private OnButtonClickListener mOnButtonClickListener ;
public ExampleAdapter(Context context,OnButtonClickListener listener) {
this.mOnButtonClickListener =listener;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
//这里也用到了activity的引用
convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item, null);
}
TextView textView = (TextView) convertView.findViewById(R.id.text);
textView.setText(String.valueOf(position));
Button button = (Button) convertView.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mOnButtonClickListener!=null){
mOnButtonClickListener.onButtonClick(button);
}
}
});
return convertView;
}
public Interface OnButtonClickListener {
void OnButtonClickListener(View view);
}
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.listView);
//这里将activity对象传入adapter
ExampleAdapter adapter = new ExampleAdapter(this,new ExampleAdapter.OnButtonClickListener(){
@override
public void onButtonClickListener(View view){
startActivity(new Intent(MainActivity.this,SecondActivity.this));
}
});
listView.setAdapter(adapter);
}
}
2.内部类
使用leakcanary检测内存泄漏
debugImplementation'com.squareup.leakcanary:leakcanary-android:1.6.2'
debugImplementation'com.squareup.leakcanary:leakcanary-support-fragment:1.6.2'
其实还有其他导入方式,区分debug版和Release版
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.2'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.2'
}
自定义一个Application类
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
if (!LeakCanary.isInAnalyzerProcess(this)) {
LeakCanary.install(this);
}
}
}
在<Application/>里加入
android:name=".MyApplication"
pull文件到pc
adb root
adb remount
adb push (目标文件) (目标目录)
adb pull (目标文件) (目标目录)