2019-09-27 17:50:53 qinchun_long 阅读数 34
  • Android Studio 开发详解

    Android Studio教程,该教材会详细介绍Android Studio如何使用,包括在Windows平台下载安装Android Studio、配置、代码重构、项目调试、jar包管理等。

    10820 人正在学习 去看看 郭宏志

第一行代码Android (第二版)看后的一些个人意见,纯属个人意见。

最近在闲暇的时间,看了一下Android的 《第一行代码(第二版)》。自己做Android也有好几年了,这本书给我的第一个感觉就是基本功很重要,比如ViewStub 这个控件,我从来没有用过,也很少见有人用ViewStub这个控件,而这个控件是为了提高显示速度而用的! ViewStub 是一个轻量级的 View,它是一个看不见的,并且不占布局位置,占用资源非 常小的视图对象。在实际开发中可能好多的基础知识我们都不重视,我们每天都为APP的优化而头疼,可是在我看第一行代码的时候,发现好多之前复杂的写法,完全可以用更简单的方式来处理,而且性能会更好!希望同学们可以重视起来基础知识!

第一行代码这本书很详细的讲解了Android的各个组件、布局、控件,适合于初学者的一本书!而且里面也讲了Android工具的安装,开发环境的配置;但是这本书里面没有Java或者kotlin的任何东西,如果正真要做自己的APP的话,读者还需要,先学习一下Java或者Kotlin!在这里建议去看看Java基础,这本书的源码就是用Java写的!这两给大家也分享两本Java的初级书!【1:《Java编程规范(第三版)》; 2:Java编程思想(第4版)】

好多初学一般都是网上直接找视频学习,而学习的关键是要练习!不管是看书还是看视频都是要手把手的去敲代码的!而看视频有人直接讲解会更好理解,而看书相对比看视频要快很多;要是之前接触过编程的同学和理解能力强的同学建议看书学习!书里面讲的更细,而且照着源码打会更容易上手!

这本书讲解用的编译工具是Android Studio,它的第一版用的是Eclipse。而随着Android Studio的普及,Gradle 也暴露出来了各式各样的问题,这本书里面并没有提到,如果遇到Gradle相关的错误,首先建议大家使用gradle的最新版本;同时从Android 5.0 以后,每个版本都有不同的变化,而因为版本产生问题也随着Android 系统的迭代不断增加,学习Android的同时也必须了解Android 各个版本的特性,和常见问题。不过通常的问题度娘上面都可以找到!第一行代码Android这本书没有涉及到开发中遇到的问题,但是他系统的讲了Android 的基础知识,是一本非常值得看的一本书!

第一行代码Android 这本书,从Android的基本控件,四大组件等,一直讲到项目实践,书中也讲了一个实战的例子,一直讲到APP的打包、上线。非常适合想学安卓的同学们!
这里把
Java编程规范(第三版)
Java编程思想(第4版)
第一行代码Android(第二版) 【附源码】
Android开发艺术探索
分享给大家!希望可以帮到大家!
百度网盘:https://pan.baidu.com/s/1ZfX_hHDd16T9K55jn3bzjQ
提取码:ywq0

2018-09-07 19:04:49 weixin_41903771 阅读数 357
  • Android Studio 开发详解

    Android Studio教程,该教材会详细介绍Android Studio如何使用,包括在Windows平台下载安装Android Studio、配置、代码重构、项目调试、jar包管理等。

    10820 人正在学习 去看看 郭宏志

        我使用的是最新版的Android studio 3.1.2版本,所以有部分内容与定义与书中的不同。希望在以后的时间里我能够想起来为这篇博客续命

目前正在跟着书学习,所以会慢慢更新,不会一下子编辑完成。

我自己犯的错误

1、UIBestPractice项目里

  • p137。在运行的时候,发现RecyclerView是一页一个消息框,经过检查,发现是msg_item.xml布局里的最外层的LinearLayout的height设置错误,应该设置为wrap_content,而我设置成了match,导致了一个屏幕一条消息。改正后正常显示。
  • p139。运行时不显示消息框。检查MainActivity。发现是布局管理器没有设置。如下两行没有加入。
LinearLayoutManager layoutManager = new LinearLayoutManager(this) ;
msgRecyclerView.setLayoutManager(layoutManager);

 

书中的错误

第一处:p137,书下方的TextView标签里的textColor没有进行设置,导致了运行的时候发送端的消息显示不是来。

 

2017-05-15 16:35:13 aoyihenshuang 阅读数 314
  • Android Studio 开发详解

    Android Studio教程,该教材会详细介绍Android Studio如何使用,包括在Windows平台下载安装Android Studio、配置、代码重构、项目调试、jar包管理等。

    10820 人正在学习 去看看 郭宏志

第一行代码Android第二章读书笔记

  1. Activity
    1.1 手动创建活动
    1.2 Toast和Menu/销毁活动
  2. Intent
    2.1 显示/隐式
    2.2 传递/返回数据
  3. 活动的生命周期
    3.1 返回栈
    3.2 活动的生命周期/启动模式
    3.3 活动被回收了怎么办?
    3.4 一种知晓当前活动的方法
    3.5 一种随时随地退出程序的方法
  4. 小结

1 Activity

活动的个人定义:一种可以和用户进行交互的窗口
打开一个安卓应用,本质就是使用各种各样的活动和用户进行交互。我把它类比为桌面图形开发中的窗口,如MFC中的Dialog窗口。

1.1手动创建活动

流程:

  1. 创建一个无活动的项目
  2. 在Java下的包中,new一个activity
  3. 在res目录下,新建(或自动创建)一个layout文件夹
  4. 在layout目录下新建(或者自动创建)一个layout源文件
  5. 对layout源文件进行修改
  6. 在AndroidManifest文件中进行注册

关键点:

-1-在activity的注册中,要配置action和category,使之成为主活动

...
        <activity android:name=".FirstActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
...

-2-一个activity对应一个layout,该代码写在onCreate中

setContentView(R.layout.first_layout);

-3-如书中在layout中添加了一个按钮,那么在activity的代码中也要new一个Button对象,并修改其内部的事件

1.2 Toast和Menu

Toast的个人定义:一个短暂的提示,悬浮出现。例如……

您正在使用2G/3G/4G网络

使用示例:

...//写在onCreate中
Button button1 = (Button) findViewById(R.id.button_1);
button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Toast.makeText(FirstActivity.this, "You clicked me! ", Toast.LENGTH_SHORT).show();
                finish();
...

可以看到,主要的用法就是Toast.makeText(上下文, "String", 时间长度),时间长度可以使用内置的长度。
另外,中间的finish();可以销毁该活动,类似于按下back键。但是,按下back键会先进行过场动画,再销毁;而使用finish();则直接销毁。详见

Menu的个人定义:一个菜单栏。例如最常见的即右上角的···
用法示例:
首先在res目录下new一个名为menu的文件夹,然后在其中new一个目录源文件。内容修改如下:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
    android:id="@+id/add_item"
    android:title="Add"/>
    <item
        android:id="@+id/remove_item"
        android:title="Remove"/>
</menu>

每一个item对应一个选项。
其后,在activity中,重写onCreateOptionsMenu()方法。重写的快捷键是Ctrl+O。

 @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

继续重写onOptionsSelected():

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()){
            case R.id.add_item:
                Toast.makeText(this, "You clicked Add!", Toast.LENGTH_SHORT).show();break;
            case R.id.remove_item:
                Toast.makeText(this, "You clicked Remove!", Toast.LENGTH_SHORT).show();break;
            default:
        }return true;
    }

Menu使用item.getItemId()获取clicked item 的id。
(顺带一提,从notepad++进化到Android Studio感觉好像从汉朝进化到了2017年的上海。)


2 Intent

intent的个人定义:一个通道,用来启动另一个Activity(就目前进度而言)

2.1显式/隐式

显式

在新建了一个活动(SecondActivity)之后,对按钮内的onClick()进行修改。

Button button1 = (Button) findViewById(R.id.button_1);
        button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });

如此,点击按钮以后,将显式地使用“意图”来打开活动。

隐式:
隐式的Intent,指定了一系列的action和category,只有同时满足两者才能完成调用。有点“对号入座”的意思。
在Manifest文件中对SecondActivity标签进行如下修改:

<activity android:name=".SecondActivity">
            <intent-filter>
                <action android:name="com.example.activitytest.ACTION_START"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

<intent-filter>添加了关于action和category的信息。从标签名也能看得出来,这是用于传递Intent信息的。
要使用隐式的Intent,要对按钮的onClick()进行如下修改:

button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Intent intent = new Intent("com.example.activityTest.ACTION_START");
                startActivity(intent);
            }
        });

由于我们的SecondActivity使用了默认的Category,所以没有给Intent附加有关Category的信息。可以这么做:

button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Intent intent = new Intent("com.example.activityTest.ACTION_START");         Intent.addCategory("com.example.activityTest.MY_CATEGORY");
                startActivity(intent);
            }
        });

光是这样还不能正常工作,要在SecondActivity中附加这样一条category标签<category android:name="com.example.activityTest.MY_CATEGORY"/>
写在<intent-filter>标签里。

使用隐式Intent访问网页
隐式Intent还有如下的用法:

 button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setData(Uri.parse("http://www.bing.com"));
                startActivity(intent);
            }
        });

Intent.ACTION_VIEW是一个内置动作,其常量值为android.intent.action.VIEW,然后通过Uri.perse()方法,将一个网址字符串解析成一个Uri对象,再调用setData方法将这个Uri对象传递进去。
点击该按钮时,将直接打开系统浏览器,访问指定网址。

另外,假设我们新建了一个Activity,打算用该活动打开特定的网页,那么我们还可以在<intent-filter>内添加<data>标签,以实现过滤的目的。详见原书P47或这里

另一个有趣的例子:使用Intent调用系统拨号界面:

 button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Intent intent = new Intent(Intent.ACTION_DIAL);
                intent.setData(Uri.parse("tel:10086"));
                startActivity(intent);
            }
        });

传递数据

在使用Intent启动活动时,可以将要传递的数据暂存在Intent中,启动另一个活动以后,再将这些数据取出来使用。
示例:将一个字符串传递给下一个活动。

button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                String data = "Hello SecondActivity";
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                intent.putExtra( "extra_data", data);
                startActivity(intent);
            }
        });

这里的putExtra()接受两个数据,第一个是key,第二个是传递的数据,有多重重载方式。
然后我们可以在SecondActivity中取出数据:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        Intent intent = getIntent();
        String data = intent.getStringExtra("extra_data");
        Log.d("SecondActivity",data);
    }

这里将Intent传来的额外信息,按key获取之后,用log打印了出来。getXxxExtra()有很多种方法,以此类推。

返回数据

如果要返回数据给上一个活动,要使用startActivityForResult()来启动活动。该方法接受两个参数,第一个还是Intent,第二个是请求码,举例:

button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                startActivityForResult(intent,1 );
            }
        });

以上是在FirstActivity中设定好的按钮事件。在SecondActivity中也设定一个按钮事件:

Button button2 = (Button) findViewById(R.id.button_2);
        button2.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Intent intent = new Intent();
                intent.putExtra("data_return", "Hello FirstActivity");
                setResult(RESULT_OK, intent);
                finish();
            }
        });

其中的关键就是setResult()用于向上一个活动返回数据。该方法接受两个参数,第一个是返回处理结果,一般只使用RESULT_OK和RESULT_CANCELED这两个值。第二个参数用于将带数据的Intent传递回去。然后调用finish()来销毁当前活动。
此时,来自SecondActivity的Intent回到了FirstActivity,重写onActivityResult()来得到返回的参数:

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch(requestCode){
            case 1: 
                if(resultCode == RESULT_OK){
                    String returnedData = data.getStringExtra("data_return");
                    Log.d("FirstActivity", returnedData);
                }
                break;
            default:        
        }
    }

可以看到,流程是这样的:
1. 使用startActivityForResult(intent, 1);指定一个请求码。
2. 使用setResult(RESULT_OK, intent);返回一个执行结果。
3. 在onActivityResult(int requestCode, int resultCode, Intent intent)中对每一个请求码,按照其返回结果做出相应处理。

这里还有一点,假如用户在SecondActivity中没有点击按钮销毁程序,而是直接使用back键(或者轻触返回——魅族大法好),就不会调用setResult(RESULT_OK, intent);方法,就无法返回数据。对此的解决方法是,在SecondActivity中重写onBackPressed()方法,代码如下所示:

@Override
    public void onBackPressed() {
        Intent intent = new Intent();
        intent.putExtra("data_return", "Hello FirstActivity");
        setResult(RESULT_OK, intent);
        finish();
    }

这样,即使用户使用back键返回,也会传递数据给FirstActivity。


3 活动的生命周期

Android使用任务(Task)来管理活动,一个任务就是一组存放在栈里的活动的集合,这个栈也被称作返回栈(Back Stack)。

3.1 返回栈

这部分的内容书上说的很详细,就不一一展开了。详见

3.2 活动的生命周期/启动模式

书上很详细。或见此

3.3 活动被回收了怎么办?

重写onSaveInstanceState()回调方法,该方法保证活动在被回收之前一定会被调用。用法如下:

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        String tempData = "Something you just typed";
        outState.putString("data_key", tempData);
    }

可以看到,这里也是使用key-value对应的。要使用这里的数据,要在onCreate(Bundle savedInstanceState)中填入savedInstanceState类(自动给你填好了),然后在方法中调用savedInstanceState.getString()

@Override
    protected void onCreate(final Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);
        if(savedInstanceState != null){
            String tempdata = savedInstanceState.getString("data_key");
            Log.d("SecondActivity", tempdata);
        }
    }

3.4 一种知晓当前活动的方法

本书中讲述了一种知晓当前所处哪一个活动的方法。
很简单,就是新建一个BaseActivity类,直接继承我们之前用的AppCompatActivity,并且重写其onCreate()方法,在其中使用Log.d("TAG", getClass().getSimpleName());静态方法直接打印出当前活动名即可。

3.5 一种随时随地退出程序的方法

其思路是新建一个类,用一个专门的List< Activity >容器来管理所有活动,并且写一个静态的add()remove()方法,还有一个终极finishAll()方法

在我们的BaseActivity类中,重写onCreate()方法,使其调用add()方法;重写onDestory()方法,使其调用remove()方法。当想要完全关闭程序的时候,直接调用finishAll()方法就可以了。


4 小结

这是《第一行代码Android 第二版》的读书笔记,本书写的非常通俗易懂,对新人十分友好,我的读书笔记几乎就是原书的摘抄——我认为这样做效率不高,又兼这是本人所写第一篇博客,行文组织方面尚不熟悉,以后将会用更加概括性的语言来叙述,并适当减少示例代码。
读书笔记从第二章开始,第一张过于琐碎,讲出来反而没有书上清楚,故不提。

2019-05-05 19:13:01 weixin_41213648 阅读数 28
  • Android Studio 开发详解

    Android Studio教程,该教材会详细介绍Android Studio如何使用,包括在Windows平台下载安装Android Studio、配置、代码重构、项目调试、jar包管理等。

    10820 人正在学习 去看看 郭宏志

前言:

今天学习了《第一行代码Android2版》第十一章---定位服务,实现一下,但在集成百度地图时首先要申请秘钥,申请秘钥要用到SHA1值,但是用作者--郭霖的方式看不到SHA1值

所以今天就来总结一下,通过Android Studio 窗口Terminal方式获取这个值的详细步骤 ,希望对大家有帮助。

备注:百度LBS开放平台的SDK下载链接已经更新到:

http://lbsyun.baidu.com/index.php?title=sdk/download&action#selected=location_all

 

正常情况下:

前提你的电脑必须安装配置Java环境,具体方法见:https://jingyan.baidu.com/article/a24b33cd59b58e19fe002bb9.html

一、获取开发版SHA1:

在此我直接用Android Studio提供的命令控制台了,毕竟做Android开发几乎都是用Android Studio了。

1、打开android studio 找到Terminal并打开,或者在最下面找到Terminal 如下图:

 

2、 输入命令  C:    进入c盘;

3、接着 输入命令   cd Users\Administrator   其中Administrator是自己的用户名  Administrator文件下有个.adnroid文件, 输入命令   cd  .android,最后就找到了.android,如图:

 

4、输入命令  keytool -list -v -keystore debug.keystore  其中debug.keystore是studio默认的keystore,按回车,然后输入秘钥:android(系统默认)    回车(秘钥库口令是看不到的)如下图:

 

这样就成功获取到开发版的SHA1值了,是不是很简单呀,那是当然! 

 

二、获取发布版的SHA1:

获取发布版的SHA1,跟获取开发版的SHA1的1、2、3步骤一样,不一样的地方就是第4步稍微不同而已。

1、同上;

2、同上;

3、同上;

4、打包签名文件

可参考Android Studio 打包签名教程, 或者看本文的简要介绍。
1)

2)

  

 

 

 

5、输入命令  keytool -list -v -keystore 文件目录\自己的签名文件 比如我的:keytool -list -v -keystore E:\签名文件\android.keystore ,接着按回车,然后输入秘钥:(我只知道我的,哈哈)    回车(秘钥库口令是看不到的)如下图:

 

这样就成功获取到发布版的SHA1值了,是不是很简单呀,那是当然!

 

没有整理与归纳的知识,一文不值!高度概括与梳理的知识,才是自己真正的知识与技能。 永远不要让自己的自由、好奇、充满创造力的想法被现实的框架所束缚,让创造力自由成长吧! 多花时间,关心他(她)人,正如别人所关心你的。理想的腾飞与实现,没有别人的支持与帮助,是万万不能的。

 

另外本人还开设了个人公众号:JiandaoStudio ,会在公众号内定期发布行业信息,以及各类免费代码、书籍、大师课程资源。

                                                  

                                            

扫码关注本人微信公众号,有惊喜奥!公众号每天定时发送精致文章!回复关键词可获得海量各类编程开发学习资料!

例如:想获得Python入门至精通学习资料,请回复关键词Python即可。

2019-04-08 10:16:45 weixin_41213648 阅读数 342
  • Android Studio 开发详解

    Android Studio教程,该教材会详细介绍Android Studio如何使用,包括在Windows平台下载安装Android Studio、配置、代码重构、项目调试、jar包管理等。

    10820 人正在学习 去看看 郭宏志

这段时间,在学习《第一行代码 Android 2版》过程中遇到了以下问题,经过各种途径都已一一解决;在此公布,仅供参考。

一、打开 Android Studio 卡在「Fetching Android SDK component information」界面。

如图:

Android Studio First Run 检测 Android SDK 及更新,由于众所周知的原因,我们会「Unable to access Android SDK add-on list」,而且大家一般也已经提前配置好了 Android SDK,真正需要更新的时候手动去 SDK Manager 更新就好了。

解决方案:

在 Android Studio 安装目录 bin/idea.properties 文件最后追加一句

disable.android.first.run=true

参考: http://ask.android-studio.org/?/article/14

二、新建工程后构建时提示找不到 appcompat-v7

Error:Failed to find: com.android.support:appcompat-v7:22.+

解决方案:

  1. 打开 SDK Manager,然后安装 Extras 下的 Android Support Repository:

  2. Rebuild 工程。

三、aidl 文件的放置

按以前 Eclipse 的方式,将 aidl 及其包目录层级放置在与自己的顶级包同级的目录下,即如下的 android/content/pm:

app/src/main
├─assets
├─java
│  ├─android
│  │  └─content
│  │      └─pm
│  └─org
│      └─mazhuang
│          └─easycleaner
└─res
   ├─drawable
   ├─layout
   ├─menu
   ...

然而这样在调用处一直报错:

Cannot resolve symbol 'IPackageStatsObserver'

解决方案:

将 aidl 文件放置在与 app/src/main/java 目录同级的 app/src/main/aidl 文件夹下。

app/src/main
├─aidl
│  └─android
│      └─content
│          └─pm
├─assets
├─java
│  └─org
│      └─mazhuang
│          └─easycleaner
└─res
   ├─drawable
   ├─layout
   ├─menu
   ...

四、在 Android Studio 里编译通过之后,命令行使用 gradlew build 为什么还是会重新下载 Gradle?

Gradle 的版本在 Android Studio 工程里有三处:

1、gradle/wrapper/gradle-wrapper.properties 文件的 distributionUrl 字段里指定的。

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip

比如这里指定的是 2.8 版本。

2、Android Studio 的 File > Project Structure > Project 里显示的。

这个实际上就是显示的「一」里的版本。

3、Android Studio 的 File > Settings > Build, Execution, Deployment > Build Tools > Gradle 里选择的是「Use default gradle wrapper (recommended)」还是「Use local gradle distribution」。

出现题目里的问题一般是由于「三」中选择的是「Use local gradle distribution」,这个选项下的「Gradle home」路径一般是指向 Android Studio 安装目录下的 Gradle 目录,比如 C:/Program Files/Android/Android Studio/gradle/gradle-2.8,而 gradlew 脚本是独立于 Android Studio 的,所以并不受其配置的影响,它是使用「一」里指定的版本,会到 ~/.gradle/wrapper/dists 目录下去寻找对应版本的 Gradle 是否已经存在,如果没有话就会去重新下载。

五、模拟器启动失败

PANIC: ANDROID_SDK_HOME is defined but could not find Nexus_5_API_23.ini file in $ANDROID_SDK_HOME/.android/avd
(Note: avd is searched in the order of $ANDROID_AVD_HOME,$ANDROID_SDK_HOME/.android/avd and $HOME/.android/avd)

实际上文件存在于 $HOME/.android/avd 目录下,但看样子如果设置了 $ANDROID_SDK_HOME 环境变量,Android Studio 在 $ANDROID_SDK_HOME/.android/avd 下找不到模拟器文件将直接报错,而不会再去找 $HOME 目录下的文件。

解决方案:

添加 $ANDROID_AVD_HOME 环境变量,值为 $HOME/.android/avd 的展开全路径。

六、debug.keystore 的存放位置

在使用高德地图 SDK 时,需要 key 与 keystore 文件的 sha1 校验通过,而我将 debug.keystore 拷贝到 $HOME/.android 目录下后发现一直提示 key 校验失败,也就是没有使用我拷贝到 $HOME/.android 目录下的 debug.keystore 来做 debug 签名。

原因是 debug.keystore 的默认存储路径是 $HOME/.android,但是如果配置了 $ANDROID_SDK_HOME,则会将 debug.keystore $ANDROID_SDK_HOME/.android 目录下。

解决方案:

将 debug.keystore 文件拷贝到 $ANDROID_SDK_HOME/.android 目录下。

BTW:

关于给 App 签名的手动、自动方法参考 Signing Your Applications

Android Studio 自动生成的 debug.keystore 的信息:

  • Keystore password: android
  • Key alias: androiddebugkey
  • Key password: android

七、一直提示 Please configure Android SDK

这是在一次电脑断电后出现的,试了一些方法,更新 Android Studio,将 SDK Platforms 删除了重新下,都不行,后来发现 Build Tools 可以更新,更新完后就好了。

More than one file was found with OS independent path

比如,在 netty-buffer-4.1.5.Final.jar 与 netty-common-4.1.5.Final.jar 中都有 META-INF/io.netty.version.properties,所以编译时报错:

More than one file was found with OS independent path 'META-INF/io.netty.versions.properties'

解决方案:

在 app/build.gradle 里添加如下内容:

android {
    packagingOptions {
        pickFirst 'META-INF/*'
    }
}

表示只保留一份该文件。

参考:Android Studio: Duplicate files copied in APK META-INF/DEPENDENCIES when compile

八、打开 uiautomatorviewer 报错

打开 uiautomatorviewer 报错,提示:

Unable to connect to adb. Check if adb is installed correctly.

实际 adb 命令是可正常使用的。

解决方法:

打开 uiautomatorviewer.bat 文件(Windows 下,其它系统可能是 .sh),找到下面这行(一般是最后一行):

call "%java_exe%" "-Djava.ext.dirs=%javaextdirs%" "-Dcom.android.uiautomator.bindir=%prog_dir%" -jar %jarpath% %*

将其中的 %prog_dir% 改为 Android SDK 的 tools 目录路径,比如:

call "%java_exe%" "-Djava.ext.dirs=%javaextdirs%" "-Dcom.android.uiautomator.bindir=D:\Android\sdk\tools" -jar %jarpath% %*

参考:In UI automator viewer Error Obtaining Device screenshot, Reason : Error Unable to connect to adb. Check if adb is installed correctly

九、is not translated in “zh”

报错信息:

Error: "app_name" is not translated in "zh" (Chinese) [MissingTranslation]

在引用了 Umeng 的 SDK 后编译报错,疑是 Umeng 包里的 values-zh 导致。

解决方案 1:

<?xml version="1.0" encoding="utf-8"?>
<resources
  xmlns:tools="http://schemas.android.com/tools"
  tools:ignore="MissingTranslation" >

解决方案 2:

在主项目的 build.gradle 里添加如下代码:

android {
    lintOptions {
        checkReleaseBuilds false
        abortOnError false
    }
}

参考:

十、一直卡在 Gradle:Resolve dependencies’app:debugCompile’

这种情况一般是 Gradle 去拉取某个 dependencies 的时候连不上导致。

一种方法是如果本地有能编译通过的其它工程,修改 compileSdkVersion 和 buildToolsVersion 及 dependencies 里的版本为能编译通过的工程的版本;另一种方法是将对应的依赖包 jar 下载到本地放到 libs 里面;还有一种思路是修改 jcenter() 为其它可用的源。

十一、更新到 Android Studio 3.0 后报错

提示信息:

Unable to resolve dependency for ':internal@packagingOptions/compileClasspath': Could not resolve project :commonlib.

Could not resolve project :commonlib.
Required by:
    project :internal
 > Unable to find a matching configuration of project :commonlib:
     - Configuration 'debugApiElements':
         - Required com.android.build.api.attributes.BuildTypeAttr 'packagingOptions' and found incompatible value 'debug'.
         - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
         - Found com.android.build.gradle.internal.dependency.VariantAttr 'debug' but wasn't required.
         - Required org.gradle.api.attributes.Usage 'java-api' and found compatible value 'java-api'.
     - Configuration 'debugRuntimeElements':
         - Required com.android.build.api.attributes.BuildTypeAttr 'packagingOptions' and found incompatible value 'debug'.
         - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
         - Found com.android.build.gradle.internal.dependency.VariantAttr 'debug' but wasn't required.
         - Required org.gradle.api.attributes.Usage 'java-api' and found incompatible value 'java-runtime'.
     - Configuration 'releaseApiElements':
         - Required com.android.build.api.attributes.BuildTypeAttr 'packagingOptions' and found incompatible value 'release'.
         - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
         - Found com.android.build.gradle.internal.dependency.VariantAttr 'release' but wasn't required.
         - Required org.gradle.api.attributes.Usage 'java-api' and found compatible value 'java-api'.
     - Configuration 'releaseRuntimeElements':
         - Required com.android.build.api.attributes.BuildTypeAttr 'packagingOptions' and found incompatible value 'release'.
         - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
         - Found com.android.build.gradle.internal.dependency.VariantAttr 'release' but wasn't required.
         - Required org.gradle.api.attributes.Usage 'java-api' and found incompatible value 'java-runtime'.

情况是有一个叫 internal 的 project 依赖一个叫 commonlib 的 module,最后查到原因如下:

internal project 的 build.gradle 文件里写了这么一段:

android {
    ...
    buildTypes {
        debug {
            signingConfig signingConfigs.release
        }
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
        packagingOptions {
            exclude 'META-INF/INDEX.LIST'
            exclude 'log4j.xml'
        }
    }
}

实际 packagingOptions 应该放到 buildTypes 之外,改成这样就 OK 了:

android {
    ...
    packagingOptions {
        exclude 'META-INF/INDEX.LIST'
        exclude 'log4j.xml'
    }

    buildTypes {
        debug {
            signingConfig signingConfigs.release
        }
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
    }
}

以前曾经通过这样修改临时掩盖了问题,让编译能过:

dependencies {
    ...
    implementation project(path: ':commonlib', configuration: 'default') // 临时方案
    // implementation project(':commonlib')  // 原来的样子
}

这样修改编译能通过,但是会有个问题,就是在 internal project 工程里调用 commonlib 的方法的地方,Ctrl + 鼠标左键,或者右键 Go To Declaration 时会跳到 ~/.gradle/caches/transforms-1/files-1.1/commonlib-release.aar 目录里的 .class 文件,而非 .java 源文件。

回答在 StackOverflow 的一个问题 下。

十二、启动模拟器提示 Intel HAXM is required to run this AVD your CPU does not support VT-x

我使用 Win10 系统,换主板之后遇到的,之前模拟器是能正常运行的。

我遇到的原因是 Hyper-V 的影响,导致无法安装 HAXM,虽然在 msconfig 里查看我的 Hyper-V 服务都已经停止,我在 BIOS 里也已经 Enable 了 Virtualization Technology 相关的选项,仍然报相同的错误。

解决步骤参考 http://blog.csdn.net/WangZuoChuan/article/details/54620016

  1. 打开管理员权限的 CMD

  2. 运行 bcdedit /copy {current} /d “Windows10 no Hyper-V

    这时会输出一个 UUID

  3. 执行 bcdedit /set {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} hypervisorlaunchtype OFF

    将 XXX 部分换成步骤 2 里输出的 UUID

  4. 在 msconfig 的「引导」里将 Windows 10 no Hyper-V 设为默认

  5. 重启

十三、Android Studio 里对所有 Activity 显示警告

警告信息:

methods findViewById(int) from android.app.Activity and findViewById(int) from android.support.v7.app.AppCompatActivity are inherited with the same signature

解决方案:

项目里有几个模块,有的 compileSdkVersion 和 targetSdkVersion 是 25,有的是 26,全部改成 26 并把 appcompat-v7 等 dependencies 也改成 26 对应版本后问题消失。(但诡异的是我后来改回 25 想复现一下,问题却不再出现了)

十四、Plugin with id ‘com.android.application’ not found

导入一个别人做的工程的时候遇到报错:

Error:(1, 0) Plugin with id 'com.android.application' not found

怀疑是使用比较老的版本的 Android Studio 创建,该工程只有一个 build.gradle 文件——我们平时创建的工程应该是有两个,一个 Project 级别的,一个 Module 级别的。

它是只有一个 Project 级别的 gradle 文件,但是内容却是 Module 级别 gradle 文件的内容。

后来在 StackOverflow 上找到 解决方案

在 build.gradle 文件顶部添加如下代码(注意 Gradle 版本与 Gradle Plugin 的版本对应):

buildscript {
    repositories {
        jcenter()
        google()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
        google()
    }
}

十五、升级后 Gradle sync 出错

从 Android Studio 3.0.1 升级到 3.1 的时候,Check for Updates... 提示超时,于是挂了代理升级。但是升级完成之后,打开以前能顺利构建的工程,提示 Cause: jcenter.bintray.com:443 failed to respond,怀疑是代理的原因,于是在 Settings 里将 HTTP Proxy 选项改为以前的 no proxy,报错变成 Connection refused: connect,搜索了一番之后找到 这个,依提示打开 ~/.gradle/gradle.properties,发现里面果然还存在代理的设置信息,删除之后重启 Android Studio,问题解决。

十六、Generate JavaDoc 提示“错误: 编码GBK的不可映射字符”

所有相关文件的编码都是 UTF-8,在 Android Studio 里没有找到设置 JavaDoc 相关的编码设置项,于是在 Generate JavaDoc 时弹出的 Specify Generate JavaDoc Scope 对话框的 Other command line arguments 一项里填入 -encoding utf-8 -charset utf-8,问题解决。

android-studio-javadoc

 

十七、升级 Gradle Plugin 版本后报错

The SourceSet 'instrumentTest' is not recognized by the Android Gradle Plugin. Perhaps you misspelled something?

android { sourceSets { } } 里的 instrumentTest.setRoot(...) 改为 androidTest.setRoot(...) 后问题解决。

十八、编译报错 Error:Execution failed for task ‘:app:transformClassesWithDexForRelease’

我这里的原因是一个 APP 依赖一个 Module,这两个使用了相同的包名,将 APP 的包名改了之后问题解决。

十九、升级到 3.1 后编辑 Gradle 文件卡顿

不止是卡顿……基本上就是整个 Android Studio 卡住几十秒没办法动的那种。在网上搜索之后发现遇到这种问题的网友还挺多,果然是垃圾软件毁我青春 :-P。

参考 https://blog.csdn.net/wangluotianxi/article/details/79757558,卡顿原因是编辑 Gradle 文件过程中一直在请求下面两个接口:

http://search.maven.org/solrsearch/select?q=g:%22com.google.android.support%22+AND+a:%22wearable%22&core=gav&rows=1&wt=json
http://search.maven.org/solrsearch/select?q=g:%22com.google.android.gms%22+AND+a:%22play-services%22&core=gav&rows=1&wt=json

而且,结果返回之前会卡住界面,而我们的网络访问这俩网址基本只能等到超时返回了,所以,临时解决方案是在 hosts 文件里添加如下内容,让这俩请求快速失败返回:

127.0.0.1 search.maven.org

暂未发现对正常功能有影响。

二十、编译报错 You should manually set the same version via DependencyResolution

Android dependency ‘org.mazhuang:commonlib’ has different version for the compile (0.0.4) and runtime (0.0.5) classpath. You should manually set the same version via DependencyResolution

Project A 使用了 Module B,A 依赖 commonlib(0.0.4),而 Module B 里引用了 commonlib(0.0.5),将 A 也改为依赖 commonlib(0.0.5) 即可。

二十一、编译报错 Please use JDK 8 or newer

Gradle Sync 的时候无法成功,报错

Gradle sync failed: Please use JDK 8 or newer

尝试 Rebuild 报错

Supplied javaHome is not a valid folder.

原因是我在 Project Settings 的 SDK Location 里手动指定了 JDK 的版本,但是后来升级了 JDK,所以原有路径失效了。

解决方法是将 Project Settings 的 SDK Location 里 JDK 的路径改为正确路径,或者省事起见可以直接勾选 Use embedded JDK 即可。

二十二、编译报错 Caused by: java.io.IOException: Cannot run program

提示找不到 NDK 工具链里的 mips64el-linux-android-strip,导致 Caused by: java.io.IOException: error=2

原因是 NDK r17 移除了对 ARMv5(armeabi)、MIPS 和 MIPS64 的支持,所以对应的工具链也没有了。

解决办法有几种:

  1. 检查 Gradle Plugin 的版本,即 project 级别的 build.gralde 文件里

     dependencies {
         classpath 'com.android.tools.build:gradle:3.1.3'
         ...
     }
    

    com.android.tools.build:gradle 的版本改为 3.1 以上。

  2. 将 NDK 版本退回 16b,或将 16b 以下的对应 mips 工具链的文件夹拷贝到 r17 的对应目录下。

                                            

扫码关注本人微信公众号,有惊喜奥!公众号每天定时发送精致文章!回复关键词可获得海量各类编程开发学习资料!

例如:想获得Python入门至精通学习资料,请回复关键词Python即可。

 

没有更多推荐了,返回首页