XP系统安装Android Studio 3.5.3并建立Java或Native C++工程,然后在安卓手机上运行
第一节 安装Android Studio 3.5.3
Android Studio 3.5.3下载地址:
Android Studio 3.5.3 December 5, 2019
Windows (32-bit): android-studio-ide-191.6010548-windows32.zip (756.1 MB)
https://redirector.gvt1.com/edgedl/android/studio/ide-zips/3.5.3.0/android-studio-ide-191.6010548-windows32.zip
解压后运行bin/studio.exe。Windows (64-bit): android-studio-ide-191.6010548-windows.zip (756.6 MB)
https://redirector.gvt1.com/edgedl/android/studio/ide-zips/3.5.3.0/android-studio-ide-191.6010548-windows.zip
解压后运行bin/studio64.exe。
Android Studio自带JRE,不需要事先安装Java。
Android Studio 3.5.3可以在Win7 SP1系统下直接解压使用。
如果是XP SP3或者64位XP SP2系统的话就必须要先安装one core api 4.0.1,否则运行不了studio.exe或者studio64.exe。
one core api 4.0.1下载地址:https://github.com/shorthorn-project/One-Core-API-Binaries/releases/download/4.0.1/One-Core-API-Binaries-4.0.1.zip
安装完成后重启电脑。
本人用的是64位Windows XP SP2系统,one core api 4.0.1安装完成后就可以成功运行studio64.exe了。
出现下面的窗口时点Cancel就行。
默认的Android SDK下载路径C:\Documents and Settings\Administrator\AppData\Local\Android\Sdk是有空格的,必须要改。
例如改成D:\Android\Sdk,路径中一定不能有空格。
下载过程中如果失败就多Retry几次。本人就遇到过几次域名解析失败,但过几分钟又能下载了。
下载完点击Finish按钮,就可以安装成功了。
第二节 建立普通Java安卓工程并运行
点击Start a new Android Studio project。
选择Empty Activity。
Save location要改成一个没有空格的路径,默认的路径C:\Documents and Settings\Administrator\AndroidStudioProjects\MyApplication是有空格的,是不能使用的。
Language要改成Java。
改完后点击Finish按钮。
进入工程后会下载gradle-5.4.1-all.zip,但是下载要很长时间。为了避免每次创建新工程都要下载一遍,可以在浏览器中下载https://services.gradle.org/distributions/gradle-5.4.1-all.zip,保存到D:\Android文件夹中。
修改工程里面的gradle-wrapper.properties文件(如F:\Projects\AndroidStudioProjects\MyApplication\gradle\wrapper\gradle-wrapper.properties)
把里面的distributionUrl改成file:///D:/Android/gradle-5.4.1-all.zip。
重启Android Studio,点击菜单栏里面的File->Sync Project with Gradle Files,就可以立即下载完成了。
点击解除阻止:
完了之后报了一个错误:ERROR: Cause: unable to find valid certification path to requested target
解决办法是打开Gradle Scripts下面的build.gradle (Project: My Application)文件,将里面的两处google()修改成maven { url 'http://maven.aliyun.com/nexus/content/repositories/google' },两处jcenter()修改成maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'},改完后点击一下上面的Try Again。
adb解除一下阻止:
sync成功:
sync成功后,就可以打开app/res/layout/activity_main.xml,看到可视化设计界面了。
现在我们尝试生成一下apk安装包。点击菜单栏的Build -> Make Project命令。
build失败,报错:
AAPT: aapt2.exe E 08-22 19:42:48 2296 2152 LoadedArsc.cpp:112] RES_TABLE_TYPE_TYPE entry offsets overlap actual entry data.
aapt2.exe E 08-22 19:42:48 2296 2152 ApkAssets.cpp:157] Failed to load 'resources.arsc' in APK 'D:\Android\Sdk\platforms\android-36\android.jar'.
error: failed to load include path D:\Android\Sdk\platforms\android-36\android.jar.
解决办法是打开Gradle Scripts下面的build.gradle (Module: app)文件。
compileSdkVersion改成28
buildToolsVersion改成"28.0.3"
targetSdkVersion改成28
改完后点击右上角的Sync Now,等一会后报错:
ERROR: Failed to install the following Android SDK packages as some licences have not been accepted.
build-tools;28.0.3 Android SDK Build-Tools 28.0.3
platforms;android-28 Android SDK Platform 28
To build this project, accept the SDK license agreements and install the missing components using the Android Studio SDK Manager.
Alternatively, to transfer the license agreements from one workstation to another, see http://d.android.com/r/studio-ui/export-licenses.html
Using Android SDK: D:\Android\Sdk
Install missing SDK package(s)
点击Install missing SDK package(s),接受一下协议。
点击Finish后,再点击一下Build->Make Project菜单,就成功了。
可以在F:\Projects\AndroidStudioProjects\MyApplication\app\build\outputs\apk\debug下成功生成app-debug.apk。
现在我们尝试一下在命令行中安装这个apk到手机上运行。
安卓手机USB驱动下载地址:https://www.onlinedown.net/soft/1116709.htm
ADB Interface驱动所在文件夹:1510571328_36999_ysy\adb_interface_usb_driver
这个驱动适用于32位和64位的XP和Win7系统。
首先用USB数据线连接手机和电脑,电脑提示发现新硬件。
开始->运行->cmd打开命令行窗口,运行命令:
D:\Android\Sdk\platform-tools\adb.exe install -t F:\Projects\AndroidStudioProjects\MyApplication\app\build\outputs\apk\debug\app-debug.apk
手机上要允许一下USB Debugging。
进度一直卡住不动,什么都不输出。这是因为,最新版本的Android SDK Platform-Tools 36.0.0已经不支持XP和Win7系统了,无法正常运行。
去网上下载旧版本的platform-tools:https://dl.google.com/android/repository/platform-tools_r23.1.0-windows.zip。
下载完后先关闭Android Studio,重启一下电脑。
重启电脑后先不要打开Android Studio,先把D:\Android\Sdk\platform-tools文件夹删除掉,把刚刚下载的platform-tools_r23.1.0-windows.zip里面的platform-tools文件夹解压到D:\Android\Sdk。
再在命令行中运行一下D:\Android\Sdk\platform-tools\adb.exe install -t F:\Projects\AndroidStudioProjects\MyApplication\app\build\outputs\apk\debug\app-debug.apk命令,就成功了。
这个时候再打开Android Studio,点击Run -> Run 'app'菜单,也能成功安装apk到手机上运行。
可以看到手机上的logcat:
因为XP系统没有Powershell,所以Terminal窗格无法使用,要Win7下才能使用。
在SDK Manager里面可以看到,Android SDK Platform-Tools的版本号是23.1。
第三节 建立Native C++安卓工程并运行
先把上一节的工程关了:
然后新建一个Native C++工程:
进去之后还是一样的先把distributionUrl改成file:///D:/Android/gradle-5.4.1-all.zip,因为从网上下载会失败。改完后一定要重启Android Studio,点击菜单栏里面的File->Sync Project with Gradle Files。
ERROR: Cause: unable to find valid certification path to requested target
一样的解决方法,打开Gradle Scripts下面的build.gradle (Project: My Application)文件,将里面的两处google()修改成maven { url 'http://maven.aliyun.com/nexus/content/repositories/google' },两处jcenter()修改成maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'},改完后点击一下上面的Try Again。
完了之后会要求我们安装NDK。
ERROR: Failed to install the following Android SDK packages as some licences have not been accepted.
ndk;29.0.13846066 NDK (Side by side) 29.0.13846066
To build this project, accept the SDK license agreements and install the missing components using the Android Studio SDK Manager.
Alternatively, to transfer the license agreements from one workstation to another, see http://d.android.com/r/studio-ui/export-licenses.html
Using Android SDK: D:\Android\Sdk
NDK 29.0.13846066版本太高,与Android Studio 3.5.3不匹配,一定要安装低版本的NDK。
在当前工程Sync失败的情况下,Tools菜单下是没有SDK Manager命令的,只能从File -> Settings菜单打开。
从File -> Settings菜单打开Settings窗口后,左边展开Apperance & Behavior -> System Settings -> Android SDK。
右边打开SDK Tools选项卡,勾选下面的Show Package Details,然后勾选安装NDK (Side by side) 21.0.6113669版本。
装完NDK后,点击File -> Project Structure菜单。
左边选择SDK Location,右边Android NDK location选择NDK的路径D:\Android\Sdk\ndk\21.0.6113669。
ERROR: CMake '3.10.2' was not found in PATH or by cmake.dir property.
Install CMake 3.10.2
点击Install CMake 3.10.2链接安装cmake。
ERROR: CMake '3.10.2' was not found in PATH or by cmake.dir property.
Set cmake.dir in local.properties to D:\Android\Sdk\cmake\3.10.2.4988404
点击Set cmake.dir in local.properties to D:\Android\Sdk\cmake\3.10.2.4988404链接,就可以成功了。
上面的Unable to execute Clang-Tidy: Cannot create property=Diagnostics for JavaBean=com.jetbrains.cidr.lang.daemon.clang.tidy.ClangTidyYamlLoader$YamlData@9aedf45 in 'string', line 2, column 1: MainSourceFile: 'F:\Projects\An不用管,不影响工程的编译和运行。
Build -> Make Project生成apk安装包。
AAPT: aapt2.exe E 08-22 20:53:53 2724 1520 LoadedArsc.cpp:112] RES_TABLE_TYPE_TYPE entry offsets overlap actual entry data.
aapt2.exe E 08-22 20:53:53 2724 1520 ApkAssets.cpp:157] Failed to load 'resources.arsc' in APK 'D:\Android\Sdk\platforms\android-36\android.jar'.
error: failed to load include path D:\Android\Sdk\platforms\android-36\android.jar.
修改build.gradle (Module: app)文件。
compileSdkVersion改成28
buildToolsVersion改成"28.0.3"
targetSdkVersion改成28
Sync一下,然后再次Make Project,成功。
Run -> Run 'app',成功。
第四节 下载并使用C++ Oboe音频库
Android Studio 3.5.3可以成功导入oboe-1.9.0,但无法成功导入最新版的oboe-1.9.3。
https://github.com/google/oboe/archive/refs/tags/1.9.0.zip(Jun 26, 2024)
https://github.com/google/oboe/archive/refs/tags/1.9.3.zip(Dec 18, 2024)
把oboe-1.9.0.zip下载下来,然后解压到一个没有空格的文件夹里面,如D:\Android。
打开app/src/main/cpp/CMakeLists.txt文件,找到末尾的target_link_libraries,在括号里面添加oboe。
然后在下面添加:
set(OBOE_DIR D:\\Android\\oboe-1.9.0)
add_subdirectory(${OBOE_DIR} ./oboe)
include_directories(${OBOE_DIR}/include)
修改完成后,点击菜单栏里面的Build -> Refresh Linked C++ Projects,然后再Build -> Make Project。
修改代码。
【com/example/myapplication/MainActivity.java】
package com.example.myapplication;import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;public class MainActivity extends AppCompatActivity {private TextView textView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// Example of a call to a native methodtextView = findViewById(R.id.sample_text);}@Overrideprotected void onPause() {super.onPause();stringFromJNI("stop");textView.setText(stringFromJNI("log"));}@Overrideprotected void onResume() {super.onResume();stringFromJNI("start");}/*** A native method that is implemented by the 'native-lib' native library,* which is packaged with this application.*/public native String stringFromJNI(String message);// Used to load the 'native-lib' library on application startup.static {System.loadLibrary("native-lib");}
}
【native-lib.cpp】
#include <jni.h>
#include <string>
#include <oboe/Oboe.h>class OboeSinePlayer: public oboe::AudioStreamDataCallback {
public:OboeSinePlayer() : logCount(0) {}virtual ~OboeSinePlayer() = default;// Call this from Activity onResume()int32_t startAudio() {std::lock_guard<std::mutex> lock(mLock);oboe::AudioStreamBuilder builder;// The builder set methods can be chained for convenience.oboe::Result result = builder.setSharingMode(oboe::SharingMode::Exclusive)->setPerformanceMode(oboe::PerformanceMode::LowLatency)->setChannelCount(kChannelCount)->setSampleRate(kSampleRate)->setSampleRateConversionQuality(oboe::SampleRateConversionQuality::Medium)->setFormat(oboe::AudioFormat::Float)->setDataCallback(this)->openStream(mStream);if (result != oboe::Result::OK) return (int32_t) result;// Typically, start the stream after querying some stream information, as well as some input from the userresult = mStream->requestStart();return (int32_t) result;}// Call this from Activity onPause()void stopAudio() {// Stop, close and delete in case not already closed.std::lock_guard<std::mutex> lock(mLock);if (mStream) {mStream->stop();mStream->close();mStream.reset();}}oboe::DataCallbackResult onAudioReady(oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) override {println("onAudioReady: numFrames=%d", numFrames);float *floatData = (float *) audioData;for (int i = 0; i < numFrames; ++i) {float sampleValue = kAmplitude * sinf(mPhase);for (int j = 0; j < kChannelCount; j++) {floatData[i * kChannelCount + j] = sampleValue;}mPhase += mPhaseIncrement;if (mPhase >= kTwoPi) mPhase -= kTwoPi;}return oboe::DataCallbackResult::Continue;}std::string getLog() {std::string log = this->log;this->log.clear();return log;}private:std::mutex mLock;std::shared_ptr<oboe::AudioStream> mStream;// Stream paramsstatic int constexpr kChannelCount = 2;static int constexpr kSampleRate = 48000;// Wave params, these could be instance variables in order to modify at runtimestatic float constexpr kAmplitude = 0.5f;static float constexpr kFrequency = 440;static float constexpr kPI = M_PI;static float constexpr kTwoPi = kPI * 2;static double constexpr mPhaseIncrement = kFrequency * kTwoPi / (double) kSampleRate;// Keeps track of where the wave isfloat mPhase = 0.0;std::string log;int logCount;void println(const char *fmt, ...) {char header[30];char buffer[256];va_list list;va_start(list, fmt);vsnprintf(buffer, sizeof(buffer), fmt, list);va_end(list);if (log.empty() || logCount % 100 != 0) {if (!log.empty()) {log += "\n";}snprintf(header, sizeof(header), "[%d] ", logCount);log += header;log += buffer;logCount++;}}
};OboeSinePlayer player;extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_stringFromJNI(JNIEnv* env,jobject that , jstring message) {std::string hello = "Hello from C++";const char *messageCstr = env->GetStringUTFChars(message, nullptr);if (messageCstr != nullptr) {if (strcmp(messageCstr, "start") == 0) {player.startAudio();} else if (strcmp(messageCstr, "stop") == 0) {player.stopAudio();} else if (strcmp(messageCstr, "log") == 0) {hello = player.getLog();}env->ReleaseStringUTFChars(message, messageCstr);}return env->NewStringUTF(hello.c_str());
}
【layout/activity_main.xml】
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><ScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:id="@+id/sample_text"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Hello World!" /></ScrollView></androidx.constraintlayout.widget.ConstraintLayout>
改完代码,Build -> Make Project,然后Run -> Run 'app',在手机上运行。
APP运行后,在手机上能听到Oboe发出的声音,是一段蜂鸣声。
按HOME键(不是返回键)关闭APP,停止播放声音。再重新打开APP,又开始播放声音了,而且APP上会有日志显示,每次显示100条。这个日志是C++代码里面的println("onAudioReady: numFrames=%d", numFrames);语句打印的。