Linux_环境配置

.profile

.profile 文件在 Linux/Unix 系统中扮演着重要的角色,它是位于用户家目录 (~/) 下的一个​​隐藏文件​​(以点开头)。它主要用于在​​登录 shell​​ 的初始化过程中为特定用户设置​​环境变量​​和​​启动程序​​。

以下是关于 .profile 文件的详细说明:

  1. ​主要目的:用户环境定制​

    • ​设置环境变量:​​ 这是 .profile 最常见的用途。你可以在这里设置 PATH(决定系统去哪里查找可执行命令)、EDITOR(默认文本编辑器)、LANG(系统语言和区域设置)、JAVA_HOMEPYTHONPATH 等等。这些变量定义了你的工作环境。
    • ​运行启动命令:​​ 你可以在登录时自动运行某些命令或小脚本。例如:
      • 显示欢迎信息或系统状态 (uptimefortuneecho "Welcome back, $USER")
      • 设置命令别名 (alias ll='ls -l')
      • 设置 shell 选项 (set -o noclobber - 防止覆盖文件)
      • 启动代理或后台服务(以前更常见,现在可能有更好的方法)
  2. ​执行时机:登录时​

    • 当你通过​​登录 shell​​ 进入系统时,.profile 文件会被自动读取和执行。
    • 什么是登录 shell?
      • 通过控制台(文本登录界面)登录。
      • 使用 ssh username@hostname 远程登录。
      • 使用 su - username 或 sudo -i(切换用户并模拟完整登录)。
      • 图形界面登录后启动的​​第一个​​终端(取决于桌面环境和终端模拟器的配置,有时是登录 shell,有时不是)。
    • ​重要:​​ 并非所有终端会话都是登录 shell。如果你只是打开一个新的终端窗口(标签页),它通常是​​非登录 shell​​,不会读取 .profile,而是读取 .bashrc(对于 bash)或类似的文件。
  3. ​与系统级配置的关系​

    • /etc/profile​: 这是一个系统级别的全局配置文件,在用户登录时,​​最先​​被执行。
    • /etc/profile.d/*.sh​: /etc/profile 通常会调用执行这个目录下所有的 .sh 脚本文件,用于存放系统级别的额外配置。
    • ~/.profile​: 在 /etc/profile 之后执行。它是用户​​定制自己登录环境​​的主要地方,可以覆盖或补充系统级别的设置。
    • ~/.bash_profile 或 ~/.bash_login (bash 特有)​​: 如果 .profile 所在的 shell 是 bash,并且用户家目录下存在 ~/.bash_profile 或 ~/.bash_login,那么 bash 会​​优先执行它们​​,而​​跳过​​ ~/.profile(除非这些文件显式地 source ~/.profile)。
    • ~/.bashrc (bash 特有)​​: 主要用于​​非登录的交互式 shell​​ (即大部分新打开的终端窗口)。在登录 shell 中,如果 ~/.bash_profile 存在,它通常会去调用 ~/.bashrc,这样登录 shell 也能获得其中的设置(别名、函数等)。
  4. ​文件命名与位置​

    • ​路径:​​ 位于用户的家目录下,即 ~/.profile 或 /home/username/.profile
    • ​兼容性:​​ .profile 是一个比较通用的名字,被 Bourne Shell (sh)、Bash、Korn Shell (ksh) 等广泛支持。它为不同 shell 提供了一个公共的配置点。
    • ​Shell 专属文件:​​ 许多用户(尤其是 bash 用户)更喜欢或习惯使用 ~/.bash_profile(用于登录 bash)和 ~/.bashrc(用于交互式非登录 bash),并将 .profile 用作备用或兼容配置。
  5. ​查看与编辑​

    • 查看:cat ~/.profile 或 less ~/.profile
    • 编辑:使用你喜欢的文本编辑器(如 nano ~/.profilevim ~/.profile)。确保你编辑的是你自己的家目录下的文件。
  6. ​重要注意事项​

    • ​生效需要:​​ 修改 .profile 后,这些更改​​不会​​立即在当前已经打开的会话中生效(因为你修改时,登录过程已经完成)。要让修改生效,你需要:
      • ​方法一 (推荐):​​ 重新登录(logout 后再 login)。
      • ​方法二:​​ 在当前的登录 shell 中执行 source ~/.profile 或 . ~/.profile 命令来强制重新加载该文件。
    • ​谨慎修改:​​ 错误的语法(比如引号不匹配、错误的变量赋值)或执行有问题的命令可能导致你登录时出错,甚至无法登录。在修改重要文件前最好备份。
    • ~/.bash_profile vs ~/.profile (bash 用户):​​ 如果 ~/.bash_profile 存在,bash 会忽略 ~/.profile。因此,很多系统默认创建的是 .profile,但如果用户创建了 .bash_profile,它就会接管。推荐做法是让 ~/.bash_profile 里简单地包含 source ~/.profile,然后再包含 source ~/.bashrc,这样可以同时兼容登录配置和交互配置。

​总结​

.profile 是个人 Linux/Unix 环境的核心配置文件之一。它在你通过登录 shell 进入系统时自动运行,其主要任务是为你定义个性化的环境变量(如 PATHEDITOR)和登录时需要运行的命令或脚本。理解它与 /etc/profile~/.bash_profile~/.bashrc 等文件的关系和执行顺序,对于有效管理和定制你的 shell 环境至关重要。

Linux配置相关

bashrc source后长期有效

Android_应用基础知识

Android应用

可以使用Kotlin、Java和C++语言编写Android应用。Android SDK工具会将代码连同任何数据和资源文件编译成一个APK(Android package, Android软件包),即带有.apk后缀的归档文件;或者Android App Bundle。

  • 一个APK文件包含Android应用在运行时的必需内容,它也是Android设备用来安装应用的文件。
  • 一个AAB文件包含一个Android应用程序项目,包括一些在运行时不需要的附加元数据。ABB是一种发布格式,是不可安装到Android设备上的,它推迟(defer)APK的生成、签名到更晚的阶段。在Google Play分发应用程序时,Google Play的服务器才生成优化后的APK,仅包含特定设备安装应用所需要的资源和代码。

每个 Android 应用都处于各自的安全沙盒中,并受以下 Android 安全功能的保护:

  • Android 操作系统是一种多用户 Linux 系统,其中每个应用都是一个不同的用户;
  • 默认情况下,系统会为每个应用分配一个唯一的 Linux 用户 ID(该 ID 仅由系统使用,应用并不知晓)。系统会为应用中的所有文件设置权限,使得只有被分配给该应用的用户id对应的用户才能访问这些文件;
  • 每个进程都拥有自己的虚拟机 (VM),因此应用代码独立于其他应用而运行。
  • 默认情况下,每个应用都在其自己的 Linux 进程内运行。Android 系统会在需要执行任何应用组件时启动该进程,然后当不再需要该进程或系统必须为其他应用恢复内存时,其便会关闭该进程。

Android系统实现了应用最少特权的原则。也就是说,默认情况下,每个应用程序只能访问其工作所需的组件,没有更多。这创造了一个非常安全的环境,在该环境中,应用程序无法访问未经许可的系统部分。但是,一个应用程序可以通过其他方法与其他应用程序共享数据,并且应用程序可以访问系统服务:

  • 可以安排两个app共享相同的Linux用户ID。在这种情况下,他们可以访问彼此的文件。为了节省系统资源,具有相同用户ID的app也可以安排在相同的Linux进程中运行并共享相同的VM。这些app还必须被签署相同的证书签名。
  • 一个app可以请求许可来访问设备数据,比如设备的定位、摄像头、蓝牙连接。用户必须明确地授予这些许可。

应用程序组件(App components)

应用程序组件是Android应用程序的重要构件模块。系统或用户可以通过每个组件来进入app。有些组件依赖其他组件。

有四大类应用程序组件:

  1. Activity
  2. Service
  3. Broadcast receiver
  4. Content provider

每种类型都有一个独特的目的,并且具有独特的生命周期,可以定义组件的创建和破坏方式。

Activity

Activity是与用户交互的切入点,代表着具有用户界面的一个屏幕。比如,一个邮箱app可能有一个activity,展示了一列新邮件,另一个activity用于撰写邮件,以及另一activity在阅读邮件。尽管这些activity共同工作去形成凝聚的用户体验,但每个activity独立于其他activity。例如,如果电子邮件app允许,其他的app可以从任意一个activity启动。比如,拍照app可以启动邮箱app的activity,以撰写一个新的邮件,由此允许用户来分享照片。

Activity促进着系统和app之间的以下关键交互:

  • 持续跟踪用户当前关心什么(屏幕上有什么),来确保系统继续运行在托管着activity的进程。
  • 了解先前使用的进程包含用户可能返回的内容(已停止的activity),因此更优先地保持这些进程。
  • 帮助app处理终止其进程的情况,便于用户返回到已恢复其之前状态的activity。
  • 为app提供一种用户流交互的实现,并让系统协调这些流。(最经典的示例是共享)

An activity is the entry point for interacting with the user. It represents a single screen with a user interface. For example, an email app might have one activity that shows a list of new emails, another activity to compose an email, and another activity for reading emails. Although the activities work together to form a cohesive user experience in the email app, each one is independent of the others. As such, a different app can start any one of these activities if the email app allows it. For example, a camera app can start the activity in the email app that composes new mail to allow the user to share a picture. An activity facilitates the following key interactions between system and app:

  • Keeping track of what the user currently cares about (what is on screen) to ensure that the system keeps running the process that is hosting the activity.
  • Knowing that previously used processes contain things the user may return to (stopped activities), and thus more highly prioritize keeping those processes around.
  • Helping the app handle having its process killed so the user can return to activities with their previous state restored.
  • Providing a way for apps to implement user flows between each other, and for the system to coordinate these flows. (The most classic example here being share.)

异步消息Intent启动组件

在四种组件类型中,有三种类型(Activity, Service, Broadcast Receiver)均通过异步消息Intent进行启动,Intent会在运行时对各个组件进行互相绑定。可以将Intent视为请求其他组件做出动作的信使,无论这个组件是属于你的app还是其他app。

需要使用Intent对象创建Intent,该对象通过定义消息来启动特定组件(显式Intent)或特定的组件类型(隐式Intent)。

对于Activity和服务,Intent 会定义要执行的操作(例如,viewsend某内容),并且可指定待操作数据的URI,以及正在启动的组件可能需要了解的信息。例如,Intent可能会传达对Activity的请求,以便显示图像或打开网页。在某些情况下,可以通过启动Activity来接收结果,这样Activity还会返回Intent中的结果。例如,您可以发出一个Intent,让用户选取某位联系人并将其返回给您。返回的Intent包含指向所选联系人的URI。

每种组件都有独特的启动方法:

  1. 可以通过传递一个Intent调用startActivity()启动一个activity或给这个activity新的事情去做。(或者startActivityForResult(),当你想让activity返回一个结果时)

清单文件(AndroidManifest.xml)

在Android系统启动应用组件之前,系统必须通过读取应用的清单文件(AndroidManifest.xml)确认组件存在。应用必须在此文件中声明其所有组件,该文件必须位于应用项目目录的根目录中。

除了声明应用的组件外,清单文件还有许多其他作用,如:

  • 确定应用需要的任何用户权限,如互联网访问权限或对用户联系人的读取权限。
  • 根据应用使用的API,声明应用所需的最低API级别
  • 声明应用使用或需要的硬件和软件功能,如相机、蓝牙服务或多点触摸屏幕。
  • 声明应用需要链接的API库(Android框架API除外),如Google地图库

声明组件

清单文件的主要任务是告知系统应用组件的相关信息。例如,清单文件可按如下所示声明Activity:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:icon="@drawable/app_icon.png" ... >
<activity android:name="com.example.project.ExampleActivity"
android:label="@string/example_label" ... >
</activity>
...
</application>
</manifest>

<application>元素中,android:icon属性指向标识应用的图标所对应的资源。

<activity>元素中,android:name属性指定Activity子类的完全限定类名,android:label属性指定用作Activity的用户可见标签的字符串。

您必须使用以下元素声明所有应用组件:

  • Activity的<activity>元素。
  • 服务的<service>元素。
  • 广播接收器的<receiver>元素。
  • 内容提供程序的<provider>元素。

如果未在清单文件中声明源代码中包含的Activity、服务和内容提供程序,则这些组件对系统不可见,因此不会运行。不过,可以BroadcastReceiver对象的形式,在清单中声明或在代码中动态创建广播接收器;以及通过调用registerReceiver(),在系统中注册广播接收器。

声明组件功能

如上文启动组件中所述,可以使用Intent来启动Activity、服务和广播接收器。您可以通过在Intent中显式命名目标组件(使用组件类名)来使用Intent。还可使用隐式Intent,通过它来描述要执行的操作类型和待操作数据(可选)。借助隐式 Intent,系统能够在设备上找到可执行该操作的组件,并启动该组件。如果有多个组件可以执行Intent所描述的操作,则由用户选择使用哪一个组件

注意:如果使用Intent来启动Service,需要使用显式Intent来确保应用的安全性。使用隐式Intent启动服务存在安全隐患,因为无法确定哪些服务将响应Intent,且用户无法看到哪些服务已启动。从Android 5.0(API级别21)开始,如果使用隐式Intent调用bindService(),系统会抛出异常。所以勿为服务声明Intent过滤器。

通过将收到的Intent与设备上其他应用的清单文件中提供的Intent过滤器进行比较,系统便可识别能响应Intent的组件。

在应用的清单文件中声明Activity时,您可以选择性地加入声明Activity功能的Intent过滤器,以便响应来自其他应用的 Intent。可以将<intent-filter>元素作为组件声明元素的子项进行添加,从而为组件声明Intent过滤器。

例如,如果构建的电子邮件应用包含用于撰写新电子邮件的Activity,则可通过声明Intent过滤器来响应“send”Intent(目的是发送新电子邮件),如下方示例所示:

1
2
3
4
5
6
7
8
9
10
11
12
<manifest ... >
...
<application ... >
<activity android:name="com.example.project.ComposeEmailActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<data android:type="*/*" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>

如果另一个应用创建包含ACTION_SEND操作的Intent并将其传递到startActivity(),则系统可能会启动您的Activity,以便用户能够草拟并发送电子邮件。

声明应用要求

Android设备多种多样,但并非所有设备都提供相同的特性和功能。以防将应用安装在缺少应用所需特性的设备上,必须通过在清单文件中声明设备和软件要求,为该应用支持的设备类型明确定义一个配置文件。其中的大多数声明只是为了提供信息,系统并不会读取它们,但Google Play等外部服务会读取它们,以便在用户通过其设备搜索应用时为用户提供过滤功能。

例如,如果应用需要相机功能,并使用Android 2.1(API级别7)中引入的 API,必须在清单文件中声明以下要求,如下方示例所示:

1
2
3
4
5
6
<manifest ... >
<uses-feature android:name="android.hardware.camera.any"
android:required="true" />
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" />
...
</manifest>

通过示例中所述的声明,没有相机且Android版本低于2.1的设备将无法从Google Play安装您的应用。不过,可以声明应用使用相机,但并不要求必须使用。在此情况下,required属性设置为false,并在运行时检查设备是否拥有相机,然后根据需要停用任何相机功能。

应用资源

Android应用并非仅包含代码,它还需要与源代码分离的资源,如图像、音频文件以及任何与应用的视觉呈现有关的内容。例如,可以通过XML文件定义Activity界面的动画、菜单、样式、颜色和布局。借助应用资源,无需修改代码即可轻松更新应用的各种特性。通过提供备用资源集,可以针对各种设备配置(如不同的语言和屏幕尺寸)优化应用。

对于在Android项目中加入的每一项资源,SDK构建工具均会定义唯一的整型ID,可以利用此ID来引用资源,这些资源或来自应用代码,或来自XML中定义的其他资源。例如,如果您的应用包含名为logo.png的图像文件(保存在res/drawable/目录中),则SDK工具会生成名为R.drawable.logo的资源ID。此ID映射到应用特定的整型数,您可以利用它来引用该图像,并将其插入您的界面。

如果提供与源代码分离的资源,则其中最重要的一个优点在于,可以提供适用于不同设备配置的备用资源。例如,通过在XML中定义界面字符串,可以将字符串翻译为其他语言,并将这些字符串保存在单独的文件中。然后,Android系统会根据向资源目录名称追加的语言限定符(如为法语字符串值追加res/values-fr/)和用户的语言设置,对界面应用相应的语言字符串。

Android支持许多不同的备用资源限定符。限定符是资源目录名称中加入的短字符串,用于定义这些资源适用的设备配置。例如,您应根据设备的屏幕方向和尺寸为Activity创建不同的布局。当设备屏幕为纵向(长型)时,可能想要一种垂直排列按钮的布局;但当屏幕为横向(宽型)时,可以按水平方向排列按钮。如要根据方向更改布局,可以定义两种不同的布局,然后对每个布局的目录名称应用相应的限定符。然后,系统会根据当前设备方向自动应用相应的布局。