Bugly

app上线之后,如何收集用户的各种闪退等问题,可以使用Bugly

  1. Bugly创建应用
    底部的参考文章有保姆级的操作介绍,这里不做赘述了。

  2. cocoapods集成
    可以参考官方的 Bugly iOS SDK 使用指南,pod集成非常的简便。
    pod 'Bugly' 保存并执行pod install,然后用后缀为.xcworkspace的文件打开工程

3.项目中接入
可以封装一个类来专门处理bug相关的所有问题,参考Demo
如果想快速使用,也可以这样简单配置

简单配置

4.发布的时同步上传符号表(手动、自动两种方式)

4.1首先什么是符号:内存地址与函数名、文件名、行号的映射表。
符号表元素如下所示:<起始地址> <结束地址> <函数> [<文件名:行号>]
为了能快速并准确地定位用户APP发生Crash的代码位置,Bugly使用符号表对APP发生Crash的程序堆栈进行解析和还原。

符号表还原前后

简单的说,就是将看不懂的日志信息,转换为项目中对应的类和方法,方便定位到问题所在的位置。

4.2 符号表手动上传到bugly后台
Bugly iOS 符号表配置这个文章详细讲解了如何获取符号表的几种方法。
上传符号表有手动和自动两种方式,我实践的是手动的方式,首先从工具中下载 符号表工具到本地。

手动上传流程1
手动上传流程2
手动上传流程3

最后cd到下载的工具目录下,终端执行下面的命令就好了(必须是java 1.8的环境)
java -jar buglyqq-upload-symbol.jar -appid d####d -appkey 4####-###-412b-###c3 -bundleid com.###.### -version 2.0.1 -platform IOS -inputSymbol ###.app.dSYM

终端流程1
终端流程2

看到最后的200就表示上传成功了,直接去bugly后台查看具体的报错就好了

4.3符号表自动上传到bugly后台

!/bin/sh

Copyright 2016 Bugly, Tencent. All rights reserved.

V1.4.0

2016.08.03

######################################################

1. 脚本集成到Xcode工程的Target

######################################################

--- Copy the SCRIPT to the Run Script of Build Phases in the Xcode project ---

BUGLY_APP_ID="d87e345d2d"

BUGLY_APP_KEY="46abf9ba-fc79-412b-89de-b92c26d02bc3"

BUNDLE_IDENTIFIER="com.botella.app"

UPLOAD_DSYM_ONLY=1

# 脚本默认配置的版本格式为CFBundleShortVersionString(CFBundleVersion), 如果你修改默认的版本格式, 请设置此变量, 如果不想修改, 请忽略此设置

CUSTOMIZED_APP_VERSION=""

# Debug模式编译是否上传,1=上传 0=不上传,默认不上传

UPLOAD_DEBUG_SYMBOLS=0

# 模拟器编译是否上传,1=上传 0=不上传,默认不上传

UPLOAD_SIMULATOR_SYMBOLS=0

#只有Archive操作时上传, 1=支持Archive上传 0=所有Release模式编译都上传

UPLOAD_ARCHIVE_ONLY=0

source dSYMUpload.sh

--- END OF SCRIPT ---

#######################################################

2. 脚本根据输入参数处理

#######################################################

#命令行下输入应用基本信息, .dSYM文件的父目录路径, 输出文件目录即可

sh dSYMUpload.sh <bugly_app_id> <bugly_app_key> <app_bundle_identifier> <app_version> <dSYM_src_dir> <bSYMBOL_dest_dir>

#注意:

# 1. dSYMUpload.sh会调用buglySymboliOS.jar进行.dSYM解析,所以依赖Java运行时环境

# 2. dSYMUpload.sh和buglySymboliOS.jar的文件路径需一致

--- CONTENT OF SCRIPT ---

Bugly服务域名

BUGLY_DSYM_UPLOAD_DOMAIN="api.bugly.qq.com"

注意jar工具的路径跟dSYMUpload.sh脚本路径一致, 请务必保证jar路径的正确性

BUGLY_SYMBOL_JAR_PATH="dsymtool/buglySymboliOS.jar"

查找添加到系统目录的jar工具

if [ ! -f "{BUGLY_SYMBOL_JAR_PATH}" ]; then BUGLY_SYMBOL_JAR_PATH="HOME/bin/buglySymboliOS.jar"
fi

打印错误信息

function exitWithMessage(){
echo "--------------------------------"
echo "{1}" echo "--------------------------------" exit{2}
}

上传bSYMBOL文件

function dSYMUpload() {
P_APP_ID="1" P_APP_KEY="2"
P_APP_BUNDLE_ID="3" P_APP_VERSION="4"
P_BSYMBOL_ZIP_FILE="$5"

P_BSYMBOL_ZIP_FILE_NAME={P_BSYMBOL_ZIP_FILE##*/} P_BSYMBOL_ZIP_FILE_NAME={P_BSYMBOL_ZIP_FILE_NAME//&/_}
P_BSYMBOL_ZIP_FILE_NAME="{P_BSYMBOL_ZIP_FILE_NAME// /_}" DSYM_UPLOAD_URL="https://{BUGLY_DSYM_UPLOAD_DOMAIN}/openapi/file/upload/symbol?app_id={P_APP_ID}&app_key={P_APP_KEY}"
echo "dSYM upload url: {DSYM_UPLOAD_URL}" echo "-----------------------------" STATUS=(/usr/bin/curl -k "{DSYM_UPLOAD_URL}" --form "api_version=1" --form "app_id={P_APP_ID}" --form "app_key={P_APP_KEY}" --form "symbolType=2" --form "bundleId={BUNDLE_IDENTIFIER}" --form "productVersion={BUGLY_APP_VERSION}" --form "fileName={P_BSYMBOL_ZIP_FILE_NAME}" --form "file=@{P_BSYMBOL_ZIP_FILE}" --verbose) echo "-----------------------------" UPLOAD_RESULT="FAILTURE" echo "Bugly server response:{STATUS}"
if [ ! "{STATUS}" ]; then echo "Error: Failed to upload the zip archive file." elif [[ "{STATUS}" == "{"reponseCode":"0"}" ]]; then
echo "Success to upload the dSYM for the app [{BUNDLE_IDENTIFIER}{BUGLY_APP_VERSION}]"
UPLOAD_RESULT="SUCCESS"
else
echo "Error: Failed to upload the zip archive file to Bugly."
fi

Remove temp dSYM archive

echo "Remove temporary zip archive: ${DSYM_ZIP_FPATH}"

/bin/rm -f "${DSYM_ZIP_FPATH}"

if [ "$?" -ne 0 ]; then
exitWithMessage "Error: Failed to remove temporary zip archive." 0
fi

echo "--------------------------------"
echo "${UPLOAD_RESULT} - dSYM upload complete."

if [[ "${UPLOAD_RESULT}" == "FAILTURE" ]]; then
echo "--------------------------------"
echo "Failed to upload the dSYM"
echo "Please check the script and try it again."
fi
}

.dSYM解析为bSYMBOL文件

function dSYMParse() {
DSYM_FILE="1" DSYM_SYMBOL_FILE="2"
echo "--------------------------------"
echo "Extract symbol info from .dSYM file. to {DSYM_SYMBOL_FILE}" (/usr/bin/java -Xms512m -Xmx1024m -Dfile.encoding=UTF8 -jar "{BUGLY_SYMBOL_JAR_PATH}" -i "{DSYM_FILE}" -o "{DSYM_SYMBOL_FILE}" ) || exitWithMessage "Error: Failed to extract symbols." 1
echo "--------------------------------"

}

执行

function run() {

CONFIG_BUGLY_APP_ID="1" CONFIG_BUGLY_APP_KEY="2"
CONFIG_BUGLY_APP_BUNDLE_IDENTIFIER="3" CONFIG_BUGLY_APP_VERSION="4"
CONFIG_DSYM_SOURCE_DIR="5" CONFIG_DSYM_DEST_DIR="6"
CONFIG_UPLOAD_DSYM_ONLY="$7"

检查必须参数是否设置

if [ ! "{CONFIG_BUGLY_APP_ID}" ]; then exitWithMessage "Error: Bugly App ID not defined. Please set 'BUGLY_APP_ID' " 0 fi if [[ "{CONFIG_BUGLY_APP_ID}" == "App ID" ]]; then
exitWithMessage "Error: Bugly App ID not defined." 0
fi
if [ ! "{CONFIG_BUGLY_APP_KEY}" ]; then exitWithMessage "Error: Bugly App Key not defined." 0 fi if [ ! "{CONFIG_BUGLY_APP_BUNDLE_IDENTIFIER}" ]; then
exitWithMessage "Error: Bundle Identifier not defined." 0
fi

if [ ! "${CONFIG_BUGLY_APP_VERSION}" ]; then
exitWithMessage "Error: App Version not defined." 0
fi

if [ ! -e "{CONFIG_DSYM_SOURCE_DIR}" ]; then exitWithMessage "Error: Invalid dir{CONFIG_DSYM_SOURCE_DIR}" 0
fi

if [ ! "{CONFIG_DSYM_DEST_DIR}" ]; then exitWithMessage "Error: Invalid dir{CONFIG_DSYM_DEST_DIR}" 0
fi

if [ ! -e "{CONFIG_DSYM_DEST_DIR}" ]; then mkdir{CONFIG_DSYM_DEST_DIR}
fi

DSYM_FOLDER="{CONFIG_DSYM_SOURCE_DIR}" IFS='\n'

echo "Scaning dSYM FOLDER: ${DSYM_FOLDER} ..."
RET="F"

for dsymFile in (find "DSYM_FOLDER" -name '*.dSYM'); do
RET="T"
echo "Found dSYM file: $dsymFile"

   DSYM_FILE_NAME=${dsymFile##*/}
   DSYM_SYMBOL_ZIP_FILE_NAME="${DSYM_FILE_NAME}.zip"
   DSYM_SYMBOL_ZIP_FILE_NAME="${DSYM_SYMBOL_ZIP_FILE_NAME// /_}"
   DSYM_SYMBOL_ZIP_FILE=${CONFIG_DSYM_DEST_DIR}/${DSYM_SYMBOL_ZIP_FILE_NAME}

   if [ $CONFIG_UPLOAD_DSYM_ONLY -eq 1 ]; then
      if [ -e $DSYM_SYMBOL_ZIP_FILE ]; then
          rm -f $DSYM_SYMBOL_ZIP_FILE
      fi
       # 如果只上传dSYM,直接压缩dSYM目录
       zip -r -j $DSYM_SYMBOL_ZIP_FILE $dsymFile -x *.plist
   else
       # 使用符号表工具来生成Symbol文件
       dSYMParse $dsymFile $DSYM_SYMBOL_ZIP_FILE
   fi

   # 上传
   dSYMUpload $CONFIG_BUGLY_APP_ID $CONFIG_BUGLY_APP_KEY $CONFIG_BUGLY_APP_BUNDLE_IDENTIFIER $CONFIG_BUGLY_APP_VERSION $DSYM_SYMBOL_ZIP_FILE

done

if [ RET = "F" ]; then exitWithMessage "No .dSYM found in{DSYM_FOLDER}" 0
fi
}

在Xcode工程中执行

function runInXcode(){
echo "Uploading dSYM to Bugly in Xcode ..."

echo "Info.Plist : ${INFOPLIST_FILE}"

BUNDLE_VERSION=(/usr/libexec/PlistBuddy -c 'Print CFBundleVersion' "{INFOPLIST_FILE}")
BUNDLE_SHORT_VERSION=(/usr/libexec/PlistBuddy -c 'Print CFBundleShortVersionString' "{INFOPLIST_FILE}")

组装Bugly默认识别的版本信息(格式为CFBundleShortVersionString(CFBundleVersion), 例如: 1.0(1))

if [ ! "{CUSTOMIZED_APP_VERSION}" ]; then BUGLY_APP_VERSION="{BUNDLE_SHORT_VERSION}({BUNDLE_VERSION})" else BUGLY_APP_VERSION="{CUSTOMIZED_APP_VERSION}"
fi

echo "--------------------------------"
echo "Prepare application information."
echo "--------------------------------"

echo "Product Name: {PRODUCT_NAME}" echo "Bundle Identifier:{BUNDLE_IDENTIFIER}"
echo "Version: {BUNDLE_SHORT_VERSION}" echo "Build:{BUNDLE_VERSION}"

echo "Bugly App ID: {BUGLY_APP_ID}" echo "Bugly App key:{BUGLY_APP_KEY}"
echo "Bugly App Version: ${BUGLY_APP_VERSION}"

echo "--------------------------------"
echo "Check the arguments ..."

检查模拟器编译是否允许上传符号

if [ "EFFECTIVE_PLATFORM_NAME" == "-iphonesimulator" ]; then if [UPLOAD_SIMULATOR_SYMBOLS -eq 0 ]; then
exitWithMessage "Warning: Build for simulator and skipping to upload. \nYou can modify 'UPLOAD_SIMULATOR_SYMBOLS' to 1 in the script." 0
fi
fi

检查是否是Release模式编译

if [ "{CONFIGURATION=}" == "Debug" ]; then if [UPLOAD_DEBUG_SYMBOLS -eq 0 ]; then
exitWithMessage "Warning: Build for debug mode and skipping to upload. \nYou can modify 'UPLOAD_DEBUG_SYMBOLS' to 1 in the script." 0
fi
fi

检查是否Archive操作

if [ UPLOAD_ARCHIVE_ONLY -eq 1 ]; then if [[ "TARGET_BUILD_DIR" == "/Archive" ]]; then
echo "Archive the package"
else
exitWithMessage "Warning: Build for NOT Archive mode and skipping to upload. \nYou can modify 'UPLOAD_ARCHIVE_ONLY' to 0 in the script." 0
fi
fi

run {BUGLY_APP_ID}{BUGLY_APP_KEY} {BUNDLE_IDENTIFIER}{BUGLY_APP_VERSION} {DWARF_DSYM_FOLDER_PATH}{BUILD_DIR}/BuglySymbolTemp ${UPLOAD_DSYM_ONLY}
}

根据Xcode的环境变量判断是否处于Xcode环境

INFO_PLIST_FILE="${INFOPLIST_FILE}"

BuildInXcode="F"
if [ -f "${INFO_PLIST_FILE}" ]; then
BuildInXcode="T"
fi

if [ $BuildInXcode = "T" ]; then
runInXcode
else
echo "\nUsage: dSYMUpload.sh <bugly_app_id> <bugly_app_key> <app_bundle_identifier> <app_version> <dSYM_src_dir> <bSYMBOL_dest_dir> [upload_dsym_only]\n"

你可以在此处直接设置BuglyAppID和BuglyAppKey,排除不常变参数的输入

BUGLY_APP_ID="1" BUGLY_APP_KEY="2"
BUNDLE_IDENTIFIER="3" BUGLY_APP_VERSION="4"
DWARF_DSYM_FOLDER_PATH="5" SYMBOL_OUTPUT_PATH="6"
UPLOAD_DSYM_ONLY=7 run{BUGLY_APP_ID} {BUGLY_APP_KEY}{BUNDLE_IDENTIFIER} {BUGLY_APP_VERSION}{DWARF_DSYM_FOLDER_PATH} {SYMBOL_OUTPUT_PATH}{UPLOAD_DSYM_ONLY}
fi

将以上内容,换上自己项目的 appid appkey bundleId后,复制到xcode中就好了。

xcode配置内容

5.Bugly查看bug详情、修复

修复好发布新版本、并同步上传新的符号表

iOS接入demo参考,基本上流程就是在官网注册好应用,直接使用就可以了。

常见问题
手动上传符号表的时候,本地没有java环境,或者java环境不匹配终端报错内容:错误:尝试打开文件buglyqq-upload-symbol.jar时出现意外错误

上传符号表报错

终端查看了java的版本是18的,版本太高了,需要java 1.8的,所以换了自己的电脑用1.8的版本就可以成功上传符号表了。

官方iOS 常见问题

参考博客
iOS集成Bugly详解
iOS Bugly符号表的配置以及使用

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容