第一份工作中的部分笔记

2020-10-04  本文已影响0人  长点点

不知不觉中,我也到了可以带新人的时候了,有必要整理一下自己的知识,发几篇文章看看了。
这些笔记都是从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.png

Message:消息。包含消息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.png
MifareClassic

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
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 (目标文件) (目标目录)
上一篇下一篇

猜你喜欢

热点阅读