第一章 开始启程——你的第一行Android代码

机器学习参数寻优:方法、实例与分析 机器学习模型的性能很大程度上依赖于其参数的选择。参数寻优(Hyperparameter Tuning)是提升模型表现的关键步骤之一。本文将详细介绍主流的参数寻优方法,包括网格搜索(Grid Search)、随机搜索(Random Search)、贝叶斯优化(Bayesian Optimization)、和超参数优化库(如Optuna和Hyperopt)等,并探讨它们的优缺点及适用场景。 阅读详情

第一章 开始启程——你的第一行Android代码

欢迎你来到Android世界!

Android发展时间线:

2003年10月,Andy Rubin等人一起创办了Android公司;

2005年8月,谷歌收购了该公司,并让Andy Rubin继续负责Android项目;

2008年,谷歌终推出了Android系统的第一个版本;

Android的发展受到重重阻挠:

乔布斯自始至终认为Android抄袭iPhone的产品,剽窃了诸多iPhone的创意,并声称一定要毁掉Android;

2010年,Linux团队将基于Linux开发的Android操作系统从Linux内核主线中除名;

甲骨文则针对Android侵犯Java知识产权一事对谷歌提起了诉讼……

谷歌的开放政策:

任何手机厂商和个人都能免费获取到Android操作系统的源码,并且可以自由地使用和定制。

三星、HTC、摩托罗拉、索爱等公司都推出了各自系列的Android手机,Android市场上百花齐放。

仅仅推出两年后,Android就超过了已经霸占市场逾十年的诺基亚Symbian,成为了全球第一大智能手机操作系统。

国内的手机厂商,小米、华为、魅族等新兴品牌都推出了相当不错的Android手机,并且也获得了市场的广泛认可.

目前Android已经占据了全球智能手机操作系统70%以上的份额。

1.1 了解全貌——Android王国简介

Android从面世以来到现在已经发布了二十几个版本了。谷歌为Android王国建立了一个完整的生态系统。手机厂商、开发者、用户之间相互依存,共同推进着Android的蓬勃发展。

1.1.1 Android系统架构

Android大致可以分为四层架构:Linux内核层、系统运行库层、应用框架层和应用层。

1.Linux内核层

Android系统是基于Linux内核的,这一层为Android设备的各种硬件提供了底层的驱动,如显示驱动、音频驱动、照相机驱动、蓝牙驱动、Wi-Fi驱动、电源管理等。

2.系统运行库层

这一层通过一些C/C++库来为Android系统提供了主要的特性支持。如SQLite库提供了数据库的支持,OpenGL|ES库提供了3D绘图的支持,Webkit库提供了浏览器内核的支持等。

同样在这一层还有Android运行时库,它主要提供了一些核心库,能够允许开发者使用Java语言来编写Android应用。另外,Android运行时库中还包含了Dalvik虚拟机(5.0系统之后改为ART运行环境),它使得每一个Android应用都能运行在独立的进程当中,并且拥有一个自己的Dalvik虚拟机实例。相较于Java虚拟机,Dalvik是专门为移动设备定制的,它针对手机内存、CPU性能有限等情况做了优化处理。

3.应用框架层

这一层主要提供了构建应用程序时可能用到的各种API, Android自带的一些核心应用就是使用这些API完成的,开发者也可以通过使用这些API来构建自己的应用程序。

4.应用层

所有安装在手机上的应用程序都是属于这一层的,比如系统自带的联系人、短信等程序,或者是你从Google Play上下载的小游戏,当然还包括你自己开发的程序。

image

1.1.2 Android已发布的版本

2008年9月,谷歌正式发布了Android 1.0系统;

随后的几年,谷歌以惊人的速度不断地更新Android系统,2.1、2.2、2.3系统的推出使Android占据了大量的市场;

2011年2月,谷歌发布了Android 3.0系统,这个系统版本是专门为平板电脑设计的,但也是Android为数不多的比较失败的版本,推出之后一直不见什么起色;

在同年的10月,谷歌又发布了Android 4.0系统,这个版本不再对手机和平板进行差异化区分,既可以应用在手机上,也可以应用在平板上。

2014年Google I/O大会上,谷歌推出了号称史上版本改动最大的Android 5.0系统,其中使用ART运行环境替代了Dalvik虚拟机,大大提升了应用的运行速度,还提出了Material Design的概念来优化应用的界面设计。除此之外,还推出了Android Wear、Android Auto、Android TV系统,从而进军可穿戴设备、汽车、电视等全新领域。

2015年GoogleI/O大会上推出了Android 6.0系统,加入运行时权限功能;

2016年Google I/O大会上推出了Android 7.0系统,加入多窗口模式功能,这也是目前最新的Android系统版本;

查看最新的数据访问:分发信息中心  |  Platform  |  Android Developers

image

1.1.3 Android应用开发特色

Android系统到底提供了哪些东西,可供我们开发出优秀的应用程序。

1.Android系统四大组件

(1)活动(Activity):是所有Android应用程序的门面,凡是在应用中你看得到的东西,都是放在活动中的。

(2)服务(Service):你无法看到它,但它会一直在后台默默地运行,即使用户退出了应用,服务仍然是可以继续运行的。

(3)广播接收器(Broadcast Receiver):广播接收器允许你的应用接收来自各处的广播消息,比如电话、短信等,当然你的应用同样也可以向外发出广播消息。

(4)内容提供器(Content Provider):为应用程序之间共享数据提供了可能,比如你想要读取系统电话簿中的联系人,就需要通过内容提供器来实现。

2.丰富的系统控件

Android系统为开发者提供了丰富的系统控件,使得我们可以很轻松地编写出漂亮的界面。

3.SQLite数据库

Android系统还自带了这种轻量级、运算速度极快的嵌入式关系型数据库。它不仅支持标准的SQL语法,还可以通过Android封装好的API进行操作,让存储和读取数据变得非常方便。

4.强大的多媒体

Android系统还提供了丰富的多媒体服务,如音乐、视频、录音、拍照、闹铃,等等,这一切你都可以在程序中通过代码进行控制,让你的应用变得更加丰富多彩。

5.地理位置定位

现在的Android手机都内置有GPS,走到哪儿都可以定位到自己的位置,发挥你的想象就可以做出创意十足的应用,如果再结合功能强大的地图功能,LBS这一领域潜力无限。

1.2 手把手带你搭建开发环境

1.2.1 准备所需要的工具
  • JDK

    JDK是Java语言的软件开发工具包,它包含了Java的运行环境、工具集合、基础类库等内容。

  • Android SDK

    Android SDK是谷歌提供的Android开发工具包,在开发Android程序时,我们需要通过引入该工具包,来使用Android相关的API。

  • Android Studio

    在很早之前,Android项目都是用Eclipse来开发的,安装ADT插件后就可以用来开发Android程序了。

    在2013年的时候,谷歌推出了一款官方的IDE工具Android Studio,由于不再是以插件的形式存在,Android Studio在开发Android程序方面要远比Eclipse强大和方便得多。

1.2.2 搭建开发环境

Android官网下载最新的开发工具,下载地址是:下载 Android Studio 和应用工具 - Android 开发者  |  Android Developers

百度网盘去下载,下载地址是:Android Studio_免费高速下载|百度网盘-分享无限制

注意:现在点击Finish按钮来启动Android Studio,一开始会让你选择是否导入之前Android Studio版本的配置,由于这是我们首次安装,这里选择不导入就可以了。

image

在点击Finish按钮,配置工作就全部完成了。然后Android Studio会尝试联网下载一些更新,等待更新完成后再点击Finish按钮就会进入Android Studio的欢迎界面

目前为止,Android开发环境就已经全部搭建完成了。

image

1.3 创建你的第一个Android项目

1.3.1 创建HelloWorld项目(注意:Language 选择Java)
  1. 在Android Studio的欢迎界面点击Start a newAndroid Studio project;

  2. pplication name表示应用名称,此应用安装到手机之后会在手机上显示该名称;

  3. Company Domain表示公司域名,如果是个人开发者;

  4. Package name表示项目的包名,Android系统就是通过包名来区分不同应用程序的,因此包名一定要具有唯一性;

  5. AndroidStudio会根据应用名称和公司域名来自动帮我们生成合适的包名,如果你不想使用默认生成的包名,也可以点击右侧的Edit按钮自行修改;

  6. Project location表示项目代码存放的位置,如果没有特殊要求的话,这里也保持默认就可以了;

  7. Android 4.0以上的系统已经占据了超过98%的Android市场份额,因此这里我们将Minimum SDK指定成API 15就可以了;

  8. Wear、TV和Android Auto这几个选项分别是用于开发可穿戴设备、电视和汽车程序的;

  9. Android Studio提供了很多种内置模板,刚开始学习,这里直接选择Empty Activity来创建一个空的活动就可以了;

    记得:配置环境变量,

    ANDROID_HONE

    C:\用户\xxxx\AppData\Local\Android\Sdk\platform-tools

1.3.2 启动模拟器

由于Android Studio自动为我们生成了很多东西,你现在不需要编写任何代码,HelloWorld项目就已经可以运行了。但是在此之前还必须要有一个运行的载体,可以是一部Android手机,也可以是Android模拟器。

暂时先使用模拟器来运行程序:

  1. 创建一个Android模拟器,观察Android Studio顶部工具栏中的图标

image

  1. Virtual Device Configuration

image

图:选择要创建的模拟器设备

  1. 选择创建Nexus 5X这台设备的模拟器

image

  1. 选择模拟器所使用的操作系统版本,Download Android 11.0系统。继续点击Next

image

  1. 确认模拟器配置

    以对模拟器的一些配置进行确认,比如说指定模拟器的名字、分辨率、横竖屏等信息,如果没有特殊需求的话,全部保持默认就可以了。

image

  1. 完成模拟器的创建,然后会弹出如图

image

  1. 点击Actions栏目中最左边的三角形按钮即可启动模拟器

image

1.3.3 运行HelloWorld

Android Studio顶部工具栏中的图标,三角形按钮是用来运行项目的。

image

运行结果:(像使用手机一样,按住鼠标向上划、向下划),Android Studio太智能了

image

1.3.4 分析你的第一个Android程序
  1. HelloWorld项目(Android模式的项目结构)

image

任何一个新建的项目都会默认使用Android模式的项目结构,但这并不是项目真实的目录结构,而是被AndroidStudio转换过的。这种项目结构简洁明了,适合进行快速开发,但是对于新手来说可能并不易于理解。

  1. 点击图中的Android区域可以切换项目结构模式

image

  1. 将项目结构模式切换成Project,这就是项目真实的目录结构

image

(1).gradle和.idea

这两个目录下放置的都是AndroidStudio自动生成的一些文件,我们无须关心,也不要去手动编辑。

(2)app

项目中的代码、资源等内容几乎都是放置在这个目录下的,我们后面的开发工作也基本都是在这个目录下进行的。

(3)build

它主要包含了一些在编译时自动生成的文件。

(4)gradle

包含了gradle wrapper的配置文件,使用gradle wrapper的方式不需要提前将gradle下载好,而是会自动根据本地的缓存情况决定是否需要联网下载gradle。

Android Studio默认没有启用gradle wrapper的方式,如果需要打开,可以点击Android Studio导航栏→File→Settings→Build, Execution,Deployment→Gradle,进行配置更改。

(5).gitignore

这个文件是用来将指定的目录或文件排除在版本控制之外的。

(6)build.gradle

项目全局的gradle构建脚本,通常这个文件中的内容是不需要修改的。

(7)gradle.properties

这个文件是全局的gradle配置文件,在这里配置的属性将会影响到项目中所有的gradle编译脚本。

(8)gradlew和gradlew.bat

这两个文件是用来在命令行界面中执行gradle命令的,其中gradlew是在Linux或Mac系统中使用的,gradlew.bat是在Windows系统中使用的。

(9)HelloWorld.iml

iml文件是所有IntelliJ IDEA项目都会自动生成的一个文件(Android Studio是基于IntelliJ IDEA开发的),用于标识这是一个IntelliJ IDEA项目,我们不需要修改这个文件中的任何内容。

(10)local.properties

这个文件用于指定本机中的AndroidSDK路径,通常内容都是自动生成的,我们并不需要修改。

除非你本机中的Android SDK位置发生了变化,那么就将这个文件中的路径改成新的位置即可。

(11)settings.gradle

这个文件用于指定项目中所有引入的模块。由于HelloWorld项目中就只有一个app模块,因此该文件中也就只引入了app这一个模块。

image

通常情况下模块的引入都是自动完成的,需要我们手动去修改这个文件的场景可能比较少。

整个项目的外层目录结构,除了app目录之外,大多数的文件和目录都是自动生成的,我们并不需要进行修改。下面我们就来对app目录下的内容进行更为详细的分析。

image

(1)build

这个目录和外层的build目录类似,主要也是包含了一些在编译时自动生成的文件,不过它里面的内容会更加更杂,我们不需要过多关心。

(2)libs

项目中使用到了第三方jar包,就需要把这些jar包都放在libs目录下,放在这个目录下的jar包都会被自动添加到构建路径里去。

(3)androidTest

用来编写Android Test测试用例的,可以对项目进行一些自动化测试。

(4)java

所有Java代码的地方,展开该目录,你将看到我们刚才创建的HelloWorldActivity文件就在里面。

(5)res

你在项目中使用到的所有图片、布局、字符串等资源都要存放在这个目录下。这个目录下还有很多子目录,图片放在drawable目录下,布局放在layout目录下,字符串放在values目录下,所以你不用担心会把整个res目录弄得乱糟糟的。

(6)AndroidManifest.xml

整个Android项目的配置文件,程序中定义的所有四大组件都需要在这个文件里注册,另外还可以在这个文件中给应用程序添加权限声明。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.zhouzhou">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.HelloWorld">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

(7)test

用来编写Unit Test测试用例的,是对项目进行自动化测试的另一种方式。

(8).gitignore

用于将app模块内的指定的目录或文件排除在版本控制之外,作用和外层的.gitignore文件类似。

(9)app.iml

IntelliJ IDEA项目自动生成的文件,我们不需要关心或修改这个文件中的内容。

(10)build.gradle

app模块的gradle构建脚本,这个文件中会指定很多项目构建相关的配置。

(11)proguard-rules.pro

用于指定项目代码的混淆规则,当代码开发完成后打成安装包文件,如果不希望代码被别人破解,通常会将代码进行混淆,从而让破解者难以阅读。

详细解析:

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

这段代码表示对MainActivity这个活动进行注册,没有在AndroidManifest.xml里注册的活动是不能使用的。

intent-filter里的两行代码非常重要:

表示MainActivity是这个项目的主活动,在手机上点击应用图标,首先启动的就是这个活动。

而在Android四大组件的时候说过,活动是Android应用程序的门面,凡是在应用中你看得到的东西,都是放在活动中的。

打开MainActivity代码如下所示:

package com.zhouzhou;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

//MainActivity是继承自AppCompatActivity的,这是一种向下兼容的Activity,可以将Activity在各个系统版本中增加的特性和功能最低兼容到Android 2.1系统。
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}
  • Activity是Android系统提供的一个活动基类,我们项目中所有的活动都必须继承它或者它的子类才能拥有活动的特性(AppCompatActivity是Activity的子类)。
  • MainActivity中有一个onCreate()方法,这个方法是一个活动被创建时必定要执行的方法,其中只有两行代码,并且没有Hello World!的字样。
  • Android程序的设计讲究逻辑和视图分离,因此是不推荐在活动中直接编写界面的,更加通用的一种做法是,在布局文件中编写界面,然后在活动中引入进来。
  • 在onCreate()方法的第二行调用了setContentView()方法,就是这个方法给当前的活动引入了一个activity_main布局,那HelloWorld!一定就是在这里定义的了!

布局文件都是定义在res/layout目录下的,当你展开layout目录,你会看到activity_main.xml这个文件。(我是直接在代码上按住Ctrl键,鼠标定位到setContentView(R.layout.activity_main)中的activity_main,点击即可进入)

注意:遇到一个小插曲,打开activity_main.xml显示的是视图,不是代码?

快捷键:Alt+Shift+左右箭头(第一个图标是显示代码)

image

activity_main.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

终于找到了,原来就是通过android:text="Hello World!" 这句代码定义的Hello World!的字样。

1.3.5 详解项目中的资源

(1)res目录

image

归纳一下:

  • 所有以drawable开头的文件夹都是用来放图片的
  • 所有以mipmap开头的文件夹都是用来放应用图标的
  • 所有以values开头的文件夹都是用来放字符串、样式、颜色等配置的
  • layout文件夹是用来放布局文件的

注:之所以有这么多mipmap开头的文件夹,是为了让程序能够更好地兼容各种设备。

drawable文件夹也是相同的道理。Android Studio没有帮我们自动生成,但是我们应该自己创建drawable-hdpi、drawable-xhdpi、drawable-xxhdpi等文件夹。

在制作程序的时候最好能够给同一张图片提供几个不同分辨率的版本,分别放在这些文件夹下,然后当程序运行的时候,会自动根据当前运行设备分辨率的高低选择加载哪个文件夹下的图片。

当然这只是理想情况,更多的时候美工只会提供给我们一份图片,这时你就把所有图片都放在drawable-xxhdpi文件夹下就好了。

(2)strings.xml文件

打开res/values/strings.xml文件:

<resources>
    <string name="app_name">HelloWorld</string>
</resources>

这里定义了一个应用程序名的字符串,我们有以下两种方式来引用它:

  • 在代码中通过R.string.app_name可以获得该字符串的引用;
  • 在XML中通过@string/app_name可以获得该字符串的引用

其中string部分是可以替换的,如果是引用的图片资源就可以替换成drawable,如果是引用的应用图标就可以替换成mipmap,如果是引用的布局文件就可以替换成layout,以此类推。

语法练习:打开AndroidManifest.xml

......
<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.HelloWorld">
        ......
    </application>

1.3.6 详解build.gradle文件

不同于Eclipse, Android Studio是采用Gradle来构建项目的。Gradle是一个非常先进的项目构建工具,它使用了一种基于Groovy的领域特定语言(DSL)来声明项目设置,摒弃了传统基于XML(如Ant和Maven)的各种烦琐配置。

HelloWorld项目中有两个build.gradle文件,一个是在最外层目录下的,一个是在app目录下的。这两个文件对构建AndroidStudio项目都起到了至关重要的作用。

  • 最外层目录下的build.gradle文件:
// Top-level build file where you can add configuration options common to all sub-projects/modules.顶层构建文件,您可以在其中添加所有子项目/模块通用的配置选项。
plugins {
    id 'com.android.application' version '7.1.0' apply false
    id 'com.android.library' version '7.1.0' apply false
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
  • app目录下的build.gradle文件:
plugins {
    
    id 'com.android.application'
    /**
    *com.android.application表示这是一个应用程序模块
    *com.android.library表示这是一个库模块
    *应用程序模块和库模块的最大区别在于,一个是可以直接运行的,一个只能作为代码库依附于别的应用程序模块来运行。
    **/
}
//下面是一个大的android闭包,可以配置项目构建的各种属性。
android {
    //compileSdk用于指定项目的编译版本,32表示使用Android 11.0系统的SDK编译(24表示使用Android 7.0系统的SDK编译)。
    compileSdk 32
   //在android闭包中又嵌套了一个defaultConfig闭包
    defaultConfig {
        //包名,后期想改可以在这里更改
        applicationId "com.zhouzhou"
        //minSdk用于指定项目最低兼容的Android系统版本
        minSdk 21
        //targetSdk指定的值表示你在该目标版本上已经做过了充分的测试,系统将会为你的应用程序启用一些最新的功能和特性。
        targetSdk 32
        //versionCode用于指定项目的版本号
        versionCode 1
        //versionName用于指定项目的版本名,和versionCode一样,在生成安装文件的时候非常重要
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    //buildTypes闭包,用于指定生成安装文件的相关配置,通常只会有两个子闭包,一个是debug,一个是release。release闭包用于指定生成正式版安装文件的配置。另外,debug闭包是可以忽略不写的,因此我们看到上面的代码中就只有一个release闭包。
    buildTypes {
        release {
            //minifyEnabled用于指定是否对项目的代码进行混淆,true表示混淆,false表示不混淆。
            minifyEnabled false
            /**
            *第一个proguard-android.txt是在Android SDK目录下的,里面是所有项目通用的混淆规则。
            *第二个proguard-rules.pro是在当前项目的根目录下的,里面可以编写当前项目特有的混淆规则。
            *需要注意的是,通过Android Studio直接运行项目生成的都是测试版安装文件,关于如何生成正式版安装文件我们将会在第15章中学习。
            **/
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}
//dependencies闭包,它可以指定当前项目所有的依赖关系。通常Android Studio项目一共有3种依赖方式:本地依赖、库依赖和远程依赖。
//本地依赖可以对本地的Jar包或目录添加依赖关系,库依赖可以对项目中的库模块添加依赖关系,远程依赖则可以对jcenter库上的开源项目添加依赖关系。
dependencies {

    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

1.4 前行必备——掌握日志工具的使用

Android中日志工具的使用方法,这对以后的Android开发之旅会有极大的帮助。

1.4.1 使用Android的日志工具Log

Android中的日志工具类是Log(android.util.Log),这个类中提供了如下5个方法来供我们打印日志。

  • Log.v()

    用于打印那些最为琐碎的、意义最小的日志信息。对应级别verbose,是Android日志里面级别最低的一种。

  • Log.d()

    用于打印一些调试信息,这些信息对你调试程序和分析问题应该是有帮助的。对应级别debug,比verbose高一级。

  • Log.i()

    用于打印一些比较重要的数据,这些数据应该是你非常想看到的、可以帮你分析用户行为数据。对应级别info,比debug高一级。

  • Log.w()

    用于打印一些警告信息,提示程序在这个地方可能会有潜在的风险,最好去修复一下这些出现警告的地方。对应级别warn,比info高一级。

  • Log.e()

    用于打印程序中的错误信息,比如程序进入到了catch语句当中。当有错误信息打印出来的时候,一般都代表你的程序出现严重问题了,必须尽快修复。对应级别error,比warn高一级。

练习:打开MainActivity,在onCreate()方法中添加一行打印日志的语句,如下所示:

package com.zhouzhou;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d("MainActivity","onCreate execute");
    }
}

小插曲:No connected device 解决:以管理员的方式运行AS

解决问题的博客地址:flutter no devices,No connected devices found; please connect a device, or see flutter.io/setup for-优快云博客

Log.d("MainActivity","onCreate execute");传入两个参数:第一个参数是tag,一般传入当前的类名就好,主要用于对打印信息进行过滤;第二个参数是msg,即想要打印的具体的内容。

image

1.4.2 为什么使用Log而不使用System.out

在真正的项目开发中,是极度不建议使用System.out.println()方法的!如果你在公司的项目中经常使用这个方法,就很有可能要挨骂了。

这个方法除了使用方便一点之外,其他就一无是处了。缺点太多了,比如日志打印不可控制、打印时间无法确定、不能添加过滤器、日志没有级别区分……Log对以上谈不上绝对好,但是已经做的相当不错了。

除了Log.v()、Log.d()、Log.i()、Log.w()、Log.w()之外,logcat中还能很轻松地添加过滤器:

image

目前只有3个过滤器:

  • Show only selected application表示只显示当前选中程序的日志;
  • Firebase是谷歌提供的一个分析工具,我们可以不用管它;
  • NoFilters相当于没有过滤器,会把所有的日志都显示出来;

我们也可以自己添加一个过滤器试试:

image

点击图Edit Filter Configuration,会弹出一个过滤器配置界面。给过滤器起名叫Myfilter,并且让它对名为data的tag进行过滤,尝试在onCreate()方法中把打印日志的语句改成Log.d("data", "onCreate execute"),然后再次运行程序,你就会在data过滤器下看到这行日志了。

image

logcat中的日志级别控制,有5个方法:

image

日志级别控制的好处就是,你可以很快地找到你所关心的那些日志。最后,看一下关键字过滤。如果使用过滤器加日志级别控制还是不能锁定到你想查看的日志内容的话,那么还可以通过关键字进行进一步的过滤。

image

输入框里输入关键字的内容,这样只有符合关键字条件的日志才会显示出来,从而能够快速定位到任何你想查看的日志。另外还有一点需要注意,关键字过滤是支持正则表达式的,有了这个特性,我们就可以构建出更加丰富的过滤条件。

由ip地址和子网掩码求网络号、主机号、广播地址(超详细) 1、用二进制数表示IP地址   在进行计算之前,我们首先要学会十进制的IP地址怎么转换为二进制的IP地址。   给出一个例子: 十进制:172.16.25.3 二进制:10101100.00010000.00011001.00000011 1、如果两台主机的网络号相同,我们就说它们是同一网段 2、主机号的意义 - 1)主机号部分全变成1,即为该网段的广播地址 - 2)主机号部分全变成0,即为该网段的网路地址(网络号) 3、如果主机号部分为x位,则该网络能容纳最大主机数为: 2的x次方-2。减2 阅读详情

相关推荐

告别第三方插件:官方Fused Library如何重塑Android库的合并与发布流程

本文详细介绍了Android官方推出的Fused Library如何替代第三方fat-aar插件,优化Android库的合并与发布流程。通过原生支持、智能依赖管理等优势,Fused Library解决了版本兼容性、依赖传递等核心痛点,提供了更稳定高效的开发体验。文章还提供了迁移实操指南和工程实践建议,帮助开发者顺利过渡到官方方案。

weixin_42561040的博客 256

《Android第一行代码》学习笔记

在进行社招面试准备的间隙,学习了《第一行代码》,对于其中比较通用且重要的知识点予以记录。

qq_43357394的博客 2068

别再瞎调了!STM32 Systick延时函数避坑指南(正点原子、野火、慧净代码对比)

本文深入解析STM32 Systick延时函数的实现差异与优化策略,对比正点原子、野火、慧净等主流方案的优缺点。针对us和ms级延时精度问题,提供避坑指南和高级优化技巧,帮助开发者根据项目需求选择最佳方案,提升嵌入式系统的定时控制精度。

weixin_28717807的博客 340

《第一行代码》 第一章:第一行Android代码

其实 Android 程序的设计讲究逻辑和视图分离,因此是不推荐在活动中直接编写界面的,更加通用的一种做法是,在布局文件中编写界面,然后在活动中引人进来。Activity 是 Android 系统提供的一个活动基类,我们项目中所有的活动都必须继承它或者它的子类才能拥有活动的特性(AppCompatActivity 是 Activity 的子类)。其中intent-filter内的两行代码很重要,表示MainActivity是这个项目的主活动,在手机上点击应用图标,首先启动的就是这个活动。

weixin_42349568的博客 2982

银河麒麟V10开机卡Logo?别慌,手把手教你进单用户模式修复(附详细命令)

本文详细解析银河麒麟V10操作系统启动时卡Logo的故障原因,并提供进入单用户模式的完整解决方案。通过GRUB引导菜单修改启动参数,执行文件系统检查、图形服务修复等关键命令,帮助用户快速恢复系统正常运行,适用于运维人员和普通用户应对紧急启动问题。

weixin_30522183的博客 392

在Windows11上安装ubuntu版linux系统并实现桌面图形化(WSL)

在Windows11上安装ubuntu版linux系统并实现桌面图形化(WSL),xfce桌面美化、安装google-chrome

NiKoJJ‘s Blog 1万+

安卓开发从0到1(基础知识2-第一个程序)

/​ 这段代码是一个用于 Android 应用程序的 XML 布局文件。它定义了一个垂直方向的 LinearLayout,其宽度和高度都设置为 match_parent,意味着它会占满其父容器的宽度和高度。在 LinearLayout 内部,有一个 id 为 “first_view” 的 TextView,其文本设置为 “Hello World”。​ 这个布局文件可以用来创建 Android 应用程序的用户界面。

m0_60390991的博客 229

DO-297标准详解:IMA系统开发与认证指南

DO-297的前言部分为读者提供了本指南的概述,说明了该标准的编写背景、主要目标、目标受众以及该文件在开发和认证集成模块化航空电子(IMA,Integrated Modular Avionics)系统中的作用。作为现代航空电子架构的重要组成部分,IMA系统大幅度简化了航空电子系统的硬件配置,增加了灵活性并降低了成本。因此,DO-297成为确保IMA系统开发、集成和认证符合适航标准的核心文件。在现代航空领域,系统复杂性逐渐增加,传统上各子系统独立运行的方式已经不适应多任务、多功能的需求。

qq_41854911的博客 1585

Android 第一行代码(第二版)学习

android第一行笔记

Redamancylove的博客 1174

vscode中运行gcc -v命令失败了,提示:gcc不是内部或外部命令...如何解决?

🏆本文收录于 《全栈Bug调优(实战版)》 专栏,该专栏专注于分享我在真实项目开发中遇到的各类疑难Bug及其深层成因,并系统提供高效、可复现的解决思路和实操方案。无论你是刚入行的新手开发者,还是拥有多年项目经验的资深工程师,本专栏都将为你提供一条系统化、高质量的问题排查与优化路径,助力你加速成长,攻克技术壁垒,迈向技术价值最大化与职业发展的更高峰🚀!

**My Coding Family** 976

使用手机录制rosbag包

使用手机作为便携式数据采集设备来录制rosbag。

weixin_38582851的博客 615

Android:你的第一行代码(HelloWorld)

你的第一行代码(HelloWorld

weixin_67789426的博客 2049

CryoEM - 冷冻电镜 基于深度学习的 从头重构(Ab-initio Reconstruction) 开源项目 教程

冷冻电镜(CryoEM) 是一种成像方式,为蛋白质和其他生命基本组成部分的动态,提供独特的观察方式。从数百万噪声和随机取向的二维投影中,以计算效率高的方式,联合估计生物大分子的姿态、三维结构和构象异质性。

AGI 1557

第一章开始启程—你的第一行Android代码

第一行代码,个人笔记,仅供参考(不喜勿喷),谢谢

LiTianL的博客 491

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

第一章 开始启程,你的第一行Android代码

第一章 开始启程,你的第一行Android代码 今天来到新校区,大三接触的第一门课程就是智能手机开发,使用的课本就是《第一行代码Android》,这本书的作者是郭霖,是一个资深的Android开发工程师,希望在这本书的引导下我能快速入门,学好Android开发。 要想学好Android,首先我们要知道Android的系统架构,这能让我们更好的理解Android是怎么工作的。

sfzls1995的博客 474

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

第一章 开始启程,你的第一行Android代码

从《第一行代码》开始,重新开启我的学习之路。

酸豆角作坊 621

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

《Android第一行代码》笔记 第一章:开始启程—你的第一行Android代码

《Android第一行代码》笔记 第一章:开始启程—你的第一行Android代码 1.1 了解全貌——Android王国简介 1.1.1 Android系统框架 系统架构大致分为四层:Linux内核层、系统运行库层、应用框架层和应用层。 Linux内核层 Android系统是基于Linux内核的,这一层为Android设备的各种硬件提供了底层的驱动。 系统运行库层 这一层通过一些C/C++库来为Android系统提供了主要的特性支持。还有Android运行时库,允许开发者使用Java来编写应用。 Dalv

Mud_Bodhisattva的博客 386

第二行代码学习笔记——第一章:开始启程——你的第一行Android代码

笔者前言最近在读郭霖大神的第二行代码,借助第二行代码,在这里我认真梳理Android知识,为了形成自己的知识体系。坚持写一系列关于第二行代码的学习笔记,一是来提升自己的学习能力,坚持每天学习; 二是给自己整理一份资料,方便以后的查阅与复习。希望能够帮助到更多的小伙伴们:Android系统是目前世界上市场占有率最高的移动操作系统。1.1 了解全貌——Android王国简介Google为Android王

JiangWeiHu的博客 4480

第一行代码学习笔记-第一章 开始启程-3.安卓Log方法介绍

有一个静态的Log类 主要使用它的5个方法,对应5个级别: Log.v() verbose Log.d() debug Log.i() info Log.w() worn Log.e() error 在逻辑代码中调用这些方法即可 一般情况下调用他们只有两个参数的方法,第一个参数表示tag,用于分类,好查找,第二个参数表示消息内容 可以在LogCat中查看打印的日志

yeehei的博客 371

第一行代码学习笔记-第一章 开始启程-2.安卓系统文件介绍

src 用于存储逻辑代码的 gen 自动生成的文件,不需要太多关注,里面有r.java assets 这个文件里主要存放系统运行中会用的文件,如果有webview了话,生成的文件也在里这存放 bin 也是系统生成的一些文件,只要知道我们编译成功后的apk也在这里面就可以了 libs 这里主要存放的是需要引用的jar,也可以是外部的jar res 这里主要有四类文件 draw

yeehei的博客 460

第一行代码学习笔记-第一章 开始启程-1.android简介

android的开发特色: 1.四大组件: 活动:也就是页面 服务:就是后台可以运行的东西 广播:就是各个应用之间可以互通消息 内容:就是可以去读取别的应用的数据,比如通讯录 2.丰富的组件 3.sqllite数据库 包含有数据库的api 4.gps定位 5.媒体功能 6.传感器

yeehei的博客 463

《第一行代码》笔记——第1章 开始启程—你的第一行Android代码

第1章 开始启程——你的第一行Android代码 《第一行代码》的第一章,讲解内容主要包括:Android简介(发展历史、系统架构)、Android Studio的简单用法、Android项目结构的分析、Log的使用等。下面仅对我个人的知识掌握情况做相关记录。

小小弱鸡程序猿的博客 866

第一行代码——Android(第一章)

目录 第1章 开始启程,你的第一行Android代码 1.1 了解全貌,Android王国简介 第1章 开始启程,你的第一行Android代码 1.1 了解全貌,Android王国简介 系统架构 linux内核层 为各种硬件提供各种驱动支持 系统运行层 通过一些c/c++库提供特性支持 SQLite库-数据库支持 OpenGL|ES库-3D绘图支持 Webkit-浏览器内核 Android运行时库

qq_41940001的博客 496

安卓第一行代码个人导读

第一章 的全部内容都值得完全操作熟练,跑出来demo,这样你才算成功走出了第一步。 第二章 中单纯讲解了活动(Activity),而Activity作为Android四大组件中最基本也是使用最频繁的部分,其重要性不言而喻。故此章也需要完全弄透,是否弄透的标准就是自由的使用Activity。如果你拿不准,可以咨询我:) 第三章 主要讲述了Android的基本控件和基本布局,

Alucard6y的博客 570

第1章开始启程——你的第一行Android代码

第1章开始启程——你的第一行Android代码1.1.1Android系统架构1.1.2Android发布版本1.1.3Android应用开发特色1.3.1创建你的第一个Android项目1.3.2启动模拟器1.3.3运行HelloWorld1.3.4分析你的第一个Android 程序app详解1.4.1使用Android的日志工具Log1.4.2过滤器**小提示**第一章总结 1.1.1Android系统架构 Android大致可以分为四层架构:Linux内核层、系统运行库层、应用框架层和应用层。 1、

Fzw1211的博客 3479

【Android】第一行Android代码启程

本文简单介绍了 Android 开发的基础知识,包括系统架构、项目结构以及 Android 日志的使用。

LiuYaoheng的博客 1053
上一篇: 页面置换算法之改进型CLOCK算法
下一篇: 第2章 先从看得到的入手——探究活动
Roderick888888
博客等级 码龄6年 295粉丝 23原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值