很久之前為老東家做了個android視頻監(jiān)控軟件,老東家的視頻設(shè)備的協(xié)議是私有的,沒有用標(biāo)準(zhǔn)的RTMP、RTSP、HLS等標(biāo)準(zhǔn)視頻流協(xié)議,幾年前此協(xié)議從攝像機(jī)前端,服務(wù)器接收與轉(zhuǎn)發(fā)以及客戶端都是我寫的,使用的是Boost的asio網(wǎng)絡(luò)框架,當(dāng)然也用了一些其他的Boost特性;解碼使用的是ffmpeg的標(biāo)準(zhǔn)264庫,顯示使用的是android的opengl顯示庫。
? 這篇文章里主要還是描述as升級后遇到的一些問題與解決方法,為了以后遇到類似問題不再從頭做起,算作是做個記錄。
問題1.org.apache.http找不到
import org.apache.http.*
提示此文件不包含了,解決很簡單,在app的gradle腳本中添加useLibrary 'org.apache.http.legacy'
android {
*****
useLibrary 'org.apache.http.legacy'
*****
}
問題2.cmake使用
之前編譯c文件使用的是ndk,現(xiàn)在as升級到3.0之后,支持cmake了,修改代碼后,可以直接編譯運(yùn)行,省去了先編譯c(c++)文件的煩惱,那就用cmake編譯文件吧,之前做過cmake 的android編譯,不過已經(jīng)是去年的事情了,再開始做的時候,又無從下手,從現(xiàn)有工程添加cmake編譯支持,需要以下幾個步驟
- 在app的gradle文件中添加相關(guān)的cmake支持,我的gradle關(guān)于cmake的支持如下
android {
compileSdkVersion 27
defaultConfig {
applicationId "xxxxxx"
***********************
ndk {
// 設(shè)置支持的SO庫架構(gòu)
abiFilters 'armeabi-v7a'//, 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
}
externalNativeBuild {
cmake {
arguments "-DANDROID_DISABLE_FATAL_LINKER_WARNINGS=TRUE", "-DANDROID_STL=c++_shared"
cppFlags " -frtti -fexceptions"
}
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
********
}
cmake放在app模塊文件夾內(nèi),具體路徑為
/工程路徑/app/CMakeLists.txt
cpp文件路徑為
/工程路徑/app/src/main/cpp/c或者c++文件
CMakeLists.txt為
# 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.4.1)
set(SOURCE_DIR ${CMAKE_SOURCE_DIR}/src/main/cpp)
set(BOOST_DIR ${CMAKE_SOURCE_DIR}/src/main/cpp/boost)
set(FFMPEG_DIR ${CMAKE_SOURCE_DIR}/src/main/cpp/ffmpeg)
ADD_DEFINITIONS(
-O3 -g -W -Wall
-Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wreserved-user-defined-literal
-Wno-deprecated -Woverloaded-virtual -Wwrite-strings
-Wl,–no-warn-shared-textrel
-fPIC
)
add_library(ffmpeg SHARED IMPORTED)
set_target_properties(ffmpeg PROPERTIES IMPORTED_LOCATION ${FFMPEG_DIR}/lib/libffmpeg.so)
add_definitions("-DBOOST_ERROR_CODE_HEADER_ONLY -DBOOST_SYSTEM_NO_DEPRECATED -DBOOST_SYSTEM_NO_LIB -DBOOST_DATE_TIME_NO_LIB -DBOOST_REGEX_NO_LIB")
add_library(boost_system STATIC IMPORTED)
set_target_properties(boost_system PROPERTIES IMPORTED_LOCATION ${BOOST_DIR}/lib/libboost_system-clang-mt-a32-1_66.a)
add_library(boost_thread STATIC IMPORTED)
set_target_properties(boost_thread PROPERTIES IMPORTED_LOCATION ${BOOST_DIR}/lib/libboost_thread-clang-mt-a32-1_66.a)
add_library(boost_atomic STATIC IMPORTED)
set_target_properties(boost_atomic PROPERTIES IMPORTED_LOCATION ${BOOST_DIR}/lib/libboost_atomic-clang-mt-a32-1_66.a)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-fatal-warnings")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fPIC")
add_library( # Sets the name of the library.
ivs
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
${SOURCE_DIR}/ivsMain.cpp
${SOURCE_DIR}/gsession.cpp
${SOURCE_DIR}/render.cpp
${SOURCE_DIR}/sn.cpp
)
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 )
target_include_directories(ivs PRIVATE
${BOOST_DIR}/include/boost-1_66/
${FFMPEG_DIR}/include/)
# 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.
ivs
ffmpeg
boost_thread
boost_system
boost_atomic
GLESv1_CM
GLESv2
EGL
OpenSLES
android
# Links the target library to the log library
# included in the NDK.
${log-lib} )
關(guān)于cmake的使用,可以參考Android Studio Cmake
問題3.boost庫的編譯
很久之前編譯過Android平臺的boost庫,幾年沒有碰,完全忘記了,此次編譯,使用的是github上的一個開源編譯項(xiàng)目 https://github.com/moritz-wundke/Boost-for-Android,把工程git下來,開始編譯,編譯shell
./build-android.sh $(NDK_ROOT)--$(NDK_ROOT)為你的ndk路徑,比如我的路徑為/opt/android/android-ndk-r16b
花很久的時間編譯完成,但是靜態(tài)鏈接庫,產(chǎn)生error
no archive symbol table (run ranlib)
我的操作系統(tǒng)是macOS 10.14.4,,此github工程的issues提到過mac這個問題,期間我也嘗試了其他的方法,都不行,算了,轉(zhuǎn)到linux平臺去編譯就行了吧,東方不亮西方亮,不求甚解,編譯腳本
./build-android.sh ndk_dir --with-libraries=thread,system,random --arch=arm64-v8a,armeabi-v7a
我的工程里只用到了thread和system庫,沒有必要全部編譯,全部編譯等的時間太長,工程里也只用了armeabi-v7a架構(gòu),2011年一般的手機(jī)都支持armeabi-v7a,多編譯一個arm64-v8a萬一以后用到,反正也沒有多長時間
問題4.boost庫的頭文件鏈接問題
cmake中的腳本:
set(BOOST_DIR ${CMAKE_SOURCE_DIR}/src/main/cpp/boost)
target_include_directories(ivs PRIVATE
${BOOST_DIR}/include/boost-1_66/)
這個頭文件大概100多兆,鏈接之后,as直接卡在 loading symbols,大概一兩個小時,只能干等,關(guān)鍵是鏈接完畢之后,想操作as,基本也是處于卡死狀態(tài),沒有辦法繼續(xù)編碼下去,這個時候boost的bcp工具來了,參考 boost工具bcp編譯,使用方式
$./dist/bin/bcp boost/algorithm/string.hpp algorithm_inc/
你的c或者cpp文件里包含了什么,就運(yùn)行一下,比如我的工程里包含了
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
#include<boost/function.hpp>
#include<boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
那么執(zhí)行
$./dist/bin/bcp boost/bind.hpp output/
$./dist/bin/bcp boost/asio.hpp output/
......
$./dist/bin/bcp boost/date_time/posix_time/posix_time_types.hpp output/
生成了頭文件只有20多兆,不能說瞬間 loading symbols完畢,幾分鐘之內(nèi)吧,可以接受,而且之后操作as也沒有卡頓現(xiàn)象,其實(shí)使用bcp也可以鏈接靜態(tài)庫,應(yīng)該可以包含實(shí)現(xiàn)文件,我嫌麻煩,直接鏈接了靜態(tài)庫
問題5.ffmpeg庫升級一些函數(shù)和結(jié)構(gòu)找不到
比如PIX_FMT_RGB565類型沒有了,相應(yīng)的是AV_PIX_FMT_RGB565替代了,網(wǎng)上資料很多,不展開了
問題6. opengles中的glDrawTexiOES函數(shù)
glDrawTexiOES not defined,但是glext.h已經(jīng)包含了,注意在包含glext.h前加上
glext.h
#define GL_GLEXT_PROTOTYPES //包含頭文件前添加
#include <GLES/glext.h>
問題7. android java調(diào)用c中實(shí)現(xiàn),找不到相關(guān)函數(shù)
比如java中有個函數(shù)
glInit(String path)
就是找不到,我的c++中實(shí)現(xiàn)
extern "C" JNIEXPORT void JNICALL com_carvedge_ivs_LIB_glInit(JNIEnv *env, jclass clazz,jstring jpath)
找了好久,以為是庫的問題,最后發(fā)現(xiàn)是在c實(shí)現(xiàn)中少了一個Java,正確的應(yīng)該是
extern "C" JNIEXPORT void JNICALL Java_com_carvedge_ivs_LIB_glInit(JNIEnv *env, jclass clazz,jstring jpath)
大概就這么多,以后想起來其他的再補(bǔ)充