练习源码 学习视频 参考资料

Process

2021/5/15~Now:学习Android Studio的使用

Notes

Introduction

TextView

Points

1.更改AVD默认路径

  1. 在想要存放的地方新建文件夹,假设命名为ADK;
  2. 打开编辑系统环境变量并点击环境变量
  3. 新建一个系统变量
    • 变量名:ANDROID_SDK_HOME
    • 变量值:ADK文件夹的路径
  4. 在AndroidStudio中新建虚拟机即可。

2.编译C++代码

教程链接

新建C++项目

  1. Tools→SDK Manager→SDK Tools · 勾选NDKCMake
  2. 新建项目选择Native C++

Android Studio会在cpp目录下默认生成native-lib.cpp文件,其中有一个返回字符串的函数如下

1
2
3
4
5
6
7
8
9
10
#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_cpp_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}

同时cpp目录下的构建脚本CMakeLists.txt文件如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.10.2)

# Declares and names the project.

project("cpp")

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
native-lib

# Sets the library as a shared library.
SHARED

# Provides a relative path to your source file(s).
native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
log-lib

# Specifies the name of the NDK library that
# you want CMake to locate.
log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
native-lib

# Links the target library to the log library
# included in the NDK.
${log-lib} )

activity_main.xml中会默认声明一个TextView控件如下

1
2
3
4
5
6
7
8
9
<TextView
android:id="@+id/sample_text"
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"/>

MainActivity.java中代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.example.cpp;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.TextView;

import com.example.cpp.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}

private ActivityMainBinding binding;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());

// Example of a call to a native method
TextView tv = binding.sampleText;
tv.setText(stringFromJNI());
}

/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
}

添加C++文件

  1. cpp目录下新建C++源文件,假定文件名为native-test
  2. 在构建脚本CMakeLists.txt文件中仿照native-lib的格式添加库
1
2
3
4
5
6
7
8
add_library( # Sets the name of the library.
native-test

# Sets the library as a shared library.
SHARED

# Provides a relative path to your source file(s).
native-test.cpp )
  1. native-test文件中添加所使用的代码,假定代码如下
1
2
3
4
5
6
7
8
9
10
11
12
#include <jni.h>
#include <string>

using namespace std;

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_cpp_MainActivity_stringFromJNITest(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++ Test";
return env->NewStringUTF(hello.c_str());
}
  1. MainActivity.java文件中引入库并声明函数
1
2
3
4
static {
System.loadLibrary("native-test");
}
public native String stringFromJNITest();

3.引入OpenCV(Failure)

  1. 到OpenCV官网Github下载SDK(OpenCV for Android)
  • 假设下载后解压到 …/…/OpenCV-android-sdk
  1. 在Android Studio中引入
  • File → New → Import Module
  • 在 Source directory 中选择 OpenCV-android-sdk/sdk/java
  • 设置引入包的名称
  1. 添加依赖

4.layout文件夹下创建子文件夹

只是创建文件夹而没有进行注册会报如下错误

URI is not registered (Settings | Languages & Frameworks | Schemas and DTDs)

解决方法如下

方法一

  1. 打开modulebuild.gradle文件并添加如下内容

所添加的代码在android内部

假设新建文件夹名为subLayoutTest

1
2
3
4
5
6
7
8
9
10
11
android {
sourceSets {
main {
res.srcDirs =
[
'src/main/res/layout/subLayoutTest',
'src/main/res'
]
}
}
}
  1. 同步 Sync now

方法二

  1. 打开modulebuild.gradle文件并添加如下内容

所添加的代码在android - buildTypes内部

假设新建文件夹名为subLayoutTest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
def listSubFile = {
def resFolder = 'src/main/res/layout'
def files = file(resFolder).listFiles()
def folders = []
files.each {
item -> folders.add(item.absolutePath)
}
folders.add(file(resFolder).parentFile.absolutePath)
return folders
}
}
  1. 同步 Sync now

5.解决Button属性background不生效的问题

打开res/values/路径下的 themes.xml文件

将其中

1
<style name="Theme.MyProjectName" parent="Theme.MaterialComponents.DayNight.DarkActionBar">

改为如下代码

1
<style name="Theme.MyProjectName" parent="Theme.MaterialComponents.DayNight.NoActionBar.Bridge" >

1
<style name="Theme.MyProjectName" parent="Theme.AppCompat.Light.DarkActionBar">

6.签名打包APK并安装到手机

  1. BuildGenerate Signed Bundle/APK
  2. 在下面窗口选择APK后点击next

1

  1. 选择相应密钥(Key Store)并点击next

若无密钥则新建密钥

2

  1. 生成APK文件

按照下图所示进行配置

3

  1. 生成APK文件后即可安装到安卓端运行

要对使用的安卓手机进行相应的设置,关闭纯净模式,允许外部来源或未知来源下载并安装程序

7.修改APP图标

方法一

此方法较为简单

  1. 将准本好的图标放入res目录下的drawable/mipmap

假设图片名为app_icon.png,图片名中必须都为小写,否则编译错误

  1. 修改AndroidManifest.xml文件中的icon/roundIcon属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myfirstapp">

<application
android:allowBackup="true"
android:icon="@drawable/app_icon"
android:label="@string/app_name"
android:roundIcon="@drawable/app_icon"
android:supportsRtl="true"
android:theme="@style/Theme.MyFirstApp">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

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

</manifest>

图片格式建议保存为.png

此外,这两个属性都能对图标进行设置,在设置时只使用一个也可以达到效果,但如果两个同时使用的话,属性指定的对象需要设置一致。若不一致,我测试结果是显示的roundIcon指定的对象

找到android:roundIcon 属性的解释:android:roundIcon 属性指定一个图标,但只有你需要给应用设置一个特别的圆形图标时才要用到这个属性。

方法二

使用Image Asset Studio,此方法较为复杂,但是应用性更强,容错率更高

8.隐藏应用标题

Method1

找到values目录下的themes.xml文件

1
2
3
4
5
6
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.MyFirstApp" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
...
</style>
</resources>

修改style

1
2
3
4
5
6
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.MyFirstApp" parent="Theme.MaterialComponents.DayNight.NoActionBar">
...
</style>
</resources>

9.复制/获取粘贴板的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 将字符串复制到粘贴板
public static void copy(Context context, String s) {
// 获取系统剪贴板
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
// 创建一个剪贴数据集,包含一个普通文本数据条目(需要复制的数据)
ClipData clipData = ClipData.newPlainText(null, s);
// 把数据集设置(复制)到剪贴板
clipboard.setPrimaryClip(clipData);
}
// 从粘贴板获取内容
public static String getCopy(Context context) {
// 获取系统剪贴板
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
// 返回数据
ClipData clipData = clipboard.getPrimaryClip();
if (clipData != null && clipData.getItemCount() > 0) {
// 从数据集中获取(粘贴)第一条文本数据
return clipData.getItemAt(0).getText().toString();
}
return null;
}

10.项目中导入Jar包

  1. 将下载好的Jar包放在app路径下的lib文件夹中
  2. 右键该Jar包并点击add as library
  3. 选择相应的模块后点击OK进行导入
  4. 导入成功