2019-05-16 15:13:09 cuper_ 阅读数 206
  • 深度学习项目实战-对抗生成网络

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 对抗生成网络在16年爆火,成了深度学习圈子里的家常话。课程首先讲解对抗生成网络基本原理,通过案例演示原理和流程。后项目实战对抗生成网络的升级版DCGAN,大家都可以基于DCGAN生成出来任何你喜欢的数据。 课程代码基于Tensorflow框架,案例与项目课时会通过debug的形式详解代码中每行的用法。

    8232 人正在学习 去看看 唐宇迪

之前一直用我的小米4测试,用着Android6.0很舒服,但是最近鄙人鸟枪换炮用上了Android8.0测试机,本来是很开心的事情,但是每当我想使用debug功能时,只要运行到断点处等个1.2秒就会闪退,也没有任何的错误提示,开始还以为是我的代码又出现了啥未知的bug,但是用我的小米4还是依旧如故,后来各种尝试,去网上各种查,最后总算找到了解决方式,现记录在案:

最终解决办法:Run->Edit Configuration->Debugger->Debug Type设置为Dual模式,则可以正常调试。

2019-03-15 14:41:42 zhuizhiye1100 阅读数 1158
  • 深度学习项目实战-对抗生成网络

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 对抗生成网络在16年爆火,成了深度学习圈子里的家常话。课程首先讲解对抗生成网络基本原理,通过案例演示原理和流程。后项目实战对抗生成网络的升级版DCGAN,大家都可以基于DCGAN生成出来任何你喜欢的数据。 课程代码基于Tensorflow框架,案例与项目课时会通过debug的形式详解代码中每行的用法。

    8232 人正在学习 去看看 唐宇迪

将项目路径不能包含中文,软件仿真即可正常运行。

2017-07-24 15:57:04 u013258802 阅读数 3077
  • 深度学习项目实战-对抗生成网络

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 对抗生成网络在16年爆火,成了深度学习圈子里的家常话。课程首先讲解对抗生成网络基本原理,通过案例演示原理和流程。后项目实战对抗生成网络的升级版DCGAN,大家都可以基于DCGAN生成出来任何你喜欢的数据。 课程代码基于Tensorflow框架,案例与项目课时会通过debug的形式详解代码中每行的用法。

    8232 人正在学习 去看看 唐宇迪

最近工作时遇到一个非常坑爹的问题,每次打包给测试的app-debug.apk总会在一部分机器上闪退,但是直接在出问题的机型上run又没有任何问题。

如果你遇到跟我一样的情况,可以往下看看,说不定能得到些提示,也欢迎跟我探讨~


闪退时的异常如下:


java.lang.RuntimeException: Unable to instantiate application package.MyApplication:
java.lang.ClassNotFoundException: Didn't find class "package.MyApplication" on path:
DexPathList[[zip file "/data/app/package-2.apk"],nativeLibraryDirectories=[/data/app-lib/package-2, /vendor/lib, /system/lib]]
...


Caused by: java.lang.ClassNotFoundException: Didn't find class "package.MyApplication" on path:
DexPathList[[zip file "/data/app/package-2.apk"],nativeLibraryDirectories=[/data/app-lib/package-2, /vendor/lib, /system/lib]]
...


这个问题困扰我好多天了,一开始还以为上传apk的过程中出现了问题

后来才发现Android Studio在不同的设备上通过 run app 生成的debug.apk包大小竟然不一样。。。


测试机型如下:

手机型号          系统版本          包大小

p10plus            7.0                    6.21MB

红米note3        6.0.1                 6.19MB

酷派8297         4.4.4                 5.87MB

...

(家里还有一台Nubia系统是5.0.1,后续带来测试后会更新)


兼容情况如下:

高版本的设备运行出的apk安装在Android L以下的设备上会报错

低版本的设备运行出的apk安装在高版本设备上正常


注意:

这个BUG并非一定会出现,我的另一个项目从未出现此情况。

仔细对比了另一个项目的各项配置,基本一模一样,但另一个项目生成的debug.apk大小稳定在14.9MB。


在一篇博文中找到一个解决方案,有需要的可以参考:http://blog.csdn.net/xufazhong/article/details/71155528


我觉得这样降级的处理方式并不好,目前我的做法是生成测试所需debug.apk的时候使用 "Build" -> "Build APK" 生成,而非在设备上直接"Run"

顺带一提使用Build APK生成的debug.apk是6.15MB


如果有哪位大神了解具体原因和更好的解决方案还望告知,先谢过了~



2018-03-14 22:10:37 Neacy_Zz 阅读数 786
  • 深度学习项目实战-对抗生成网络

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 对抗生成网络在16年爆火,成了深度学习圈子里的家常话。课程首先讲解对抗生成网络基本原理,通过案例演示原理和流程。后项目实战对抗生成网络的升级版DCGAN,大家都可以基于DCGAN生成出来任何你喜欢的数据。 课程代码基于Tensorflow框架,案例与项目课时会通过debug的形式详解代码中每行的用法。

    8232 人正在学习 去看看 唐宇迪

本文主要分析在debug环境下Android是怎么加载到bundle文件的主要加载流程,不涉及太底层的代码均是Java代码分析。

开始

首先我们也在AndroidStudio中多多少少看过RN的源码,也知道它其实就是一个ReactRootView,而且是通过下面这段代码进行加载相对应的视图呈现我们要的UI效果:

mReactRootView.startReactApplication(
              getReactNativeHost().getReactInstanceManager(),
              mainComponentName,
              getLaunchOptions());

可以知道mainComponentName这个是我们重写了ReactActivity中相对应的

public String getMainComponentName() {
        return "RN_Demo";
    }

但是ReactInstanceManager这个类了解的还是比较,根据代码的追踪还是比较容易的就找到了相对应的初始化代码:

protected ReactInstanceManager createReactInstanceManager() {
  ReactInstanceManagerBuilder builder = ReactInstanceManager.builder()
    .setApplication(mApplication)
    .setJSMainModulePath(getJSMainModuleName())
    .setUseDeveloperSupport(getUseDeveloperSupport())
    .setRedBoxHandler(getRedBoxHandler())
    .setJavaScriptExecutorFactory(getJavaScriptExecutorFactory())
    .setUIImplementationProvider(getUIImplementationProvider())
    .setInitialLifecycleState(LifecycleState.BEFORE_CREATE);

  for (ReactPackage reactPackage : getPackages()) {
    builder.addPackage(reactPackage);
  }

  String jsBundleFile = getJSBundleFile();
  if (jsBundleFile != null) {
    builder.setJSBundleFile(jsBundleFile);
  } else {
    builder.setBundleAssetName(Assertions.assertNotNull(getBundleAssetName()));
  }
  return builder.build();
}

为什么要看这些代码,主要是为了在debug环境的时候能明白这些参数是什么从哪里来,所以这里主要关系下面两个函数:

// 返回用于拼接bundle的名字
protected String getJSMainModuleName() {
  return "index.android";
}

// debug的时候是返回true
public boolean getUseDeveloperSupport() {
  return BuildConfig.DEBUG;
}

记住这两个方法之后,我们继续看ReactRootView的加载代码:createReactContextInBackground -> recreateReactContextInBackgroundInner
然后这边涉及到了一个全新的类DevSupportManager这个是一个接口他的具体实现类:
DisabledDevSupportManager: 用于线上的版本
DevSupportManagerImpl: 用于debug的版本

// DevSupportManager的初始化方式:
mDevSupportManager =
        DevSupportManagerFactory.create(
            applicationContext,
            createDevHelperInterface(),
            mJSMainModulePath,
            useDeveloperSupport,
            redBoxHandler,
            devBundleDownloadListener,
            minNumShakes);

根据ReactInstanceManager的初始化我们可以知道 mJSMainModulePath = getJSMainModuleName() = “index.android” .. 然后我们很自然的跟进入看看是怎么初始化的原来是通过反射大法:

String className =
        new StringBuilder(DEVSUPPORT_IMPL_PACKAGE)
          .append(".")
          .append(DEVSUPPORT_IMPL_CLASS)
          .toString();
      Class<?> devSupportManagerClass =
        Class.forName(className);
      Constructor constructor =
        devSupportManagerClass.getConstructor(
          Context.class,
          ReactInstanceManagerDevHelper.class,
          String.class,
          boolean.class,
          RedBoxHandler.class,
          DevBundleDownloadListener.class,
          int.class);
      return (DevSupportManager) constructor.newInstance(
        applicationContext,
        reactInstanceManagerHelper,
        packagerPathForJSBundleName,
        true,
        redBoxHandler,
        devBundleDownloadListener,
        minNumShakes);

当然如果是非debug的时候会返回:

if (!enableOnCreate) {
  return new DisabledDevSupportManager();
}

不容易呀,终于是找到debug相关的类,既然初始化完成了那么我们就进入看看里面做了什么?

加载

我们在DevSupportManagerImpl的构造函数中重点关注一些重要类的初始化:

// DevServerHelper初始化
  public DevServerHelper(DevInternalSettings settings, String packageName) {
    mSettings = settings;
    mClient = new OkHttpClient.Builder()
      .connectTimeout(HTTP_CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS)
      .readTimeout(0, TimeUnit.MILLISECONDS)
      .writeTimeout(0, TimeUnit.MILLISECONDS)
      .build();
    mBundleDownloader = new BundleDownloader(mClient);

    mRestartOnChangePollingHandler = new Handler();
    mPackageName = packageName;
  }

很显然这里主要是初始化了一个OkHttpClient对象,自然这里肯定是用于请求地址用的。

mJSBundleTempFile = new File(applicationContext.getFilesDir(), JS_BUNDLE_FILE_NAME);

初始化了一个ReactNativeDevBundle.js文件
很好一切都就绪之后开始执行mDevSupportManager.handleReloadJS这个方法:

  public void handleReloadJS() {
  // 其他的代码都忽略只看这部分的代码即可
    PrinterHolder.getPrinter()
          .logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: load from Server");
      String bundleURL =
        mDevServerHelper.getDevServerBundleURL(Assertions.assertNotNull(mJSAppBundleName));
      reloadJSFromServer(bundleURL);
  }

重要部分的来了mDevServerHelper.getDevServerBundleURL:

  public String getDevServerBundleURL(final String jsModulePath) {
    return createBundleURL(
        mSettings.getPackagerConnectionSettings().getDebugServerHost(),
        jsModulePath,
        getDevMode(),
        getJSMinifyMode(),
        mSettings.isBundleDeltasEnabled());
  }

跟着流程继续看是怎么拼接host地址的getDebugServerHost进入这个方法最后会发现:

public static final String EMULATOR_LOCALHOST = "10.0.2.2";
public static final String GENYMOTION_LOCALHOST = "10.0.3.2";
public static final String DEVICE_LOCALHOST = "localhost";

private static String getServerIpAddress(int port) {
    // Since genymotion runs in vbox it use different hostname to refer to adb host.
    // We detect whether app runs on genymotion and replace js bundle server hostname accordingly

    String ipAddress;
    if (isRunningOnGenymotion()) {
      ipAddress = GENYMOTION_LOCALHOST;
    } else if (isRunningOnStockEmulator()) {
      ipAddress = EMULATOR_LOCALHOST;
    } else {
      ipAddress = DEVICE_LOCALHOST;
    }

    return String.format(Locale.US, "%s:%d", ipAddress, port);
  }

这边系统还会判断是否是Genymotion或者自带的Emulator模拟器,当然这些我们都没有设置,所以这里直接返回的是DEVICE_LOCALHOST这个本地的地址,所以最后的拼接出来的的地址是:localHost:8081 ..
然后我们回到createBundleURL这个方法中得到最最最最最终的拼接地址是:

http://localHost:8081/index.android.bundle?platform=android&dev=true&jsMinify=false

然后我们前面已经初始化好了OKHttpClient对象,接下来就是执行这个地址文件的下载,并下载到mJSBundleTempFile也就是ReactNativeDevBundle.js这个文件并保存到我们Context.getFilesDir路径下面。

最后我们下载成功之后会回调到ReactInstanceManager类的

  private void onJSBundleLoadedFromServer() {
    Log.d(ReactConstants.TAG, "ReactInstanceManager.onJSBundleLoadedFromServer()");
    recreateReactContextInBackground(
        mJavaScriptExecutorFactory,
        JSBundleLoader.createCachedBundleFromNetworkLoader(
            mDevSupportManager.getSourceUrl(), mDevSupportManager.getDownloadedJSBundleFile()));
  }

然后继续recreateReactContextInBackground这个方法下去,这个方法那就做太多事情了,里面涉及到jni相关的能力有限分析不下去了,所以就此结束了。

总结

在我们写完RN代码的时候 react-native run-android 命令启动后你能看到:
我们会启动一个Http服务并监听8081端口,然后我们把我们写的效果经过Android一系列的构造流程打包成apk并安装。在我们敲入命令的时候我们会发现:

request:/index.android.bundle?platform=android&dev=true

大致原理:RN会在我们本地帮我们把相关的数据打包完成并上传到这个地址去,所以我们在debug的时候可以通过下载得到相对应的bundle文件。

额外发现

我们在生成这个下载地址的时候是否发现这么一行代码:

  public String getDebugServerHost() {

    String hostFromSettings = mPreferences.getString(PREFS_DEBUG_SERVER_HOST_KEY, null);
    if (!TextUtils.isEmpty(hostFromSettings)) {
      return Assertions.assertNotNull(hostFromSettings);
    }
    return host;
  }

也就是说如果PREFS_DEBUG_SERVER_HOST_KEY这个对应的Preferences不为空那么我们就从这个地址上加载相对应的bundle文件,所以我们可以根据这个原理弄个输入框只要写入ip以及端口我们就能读取别人写好的RN并实现调试了,如:

PreferenceManager.getDefaultSharedPreferences(applicationContext)
.put("192.168.1.1:8081");

是吧,这样子我们就能直接读取这个ip下的bundle文件了,当然前提是要存在相对应的bundle文件。

稍微走了一遍流程清楚多了只怎么个加载原理,当然Android跟RN交互的底层代码还是很大的一部分代码,有待分析理解。

2016-03-02 17:27:29 jii158249628485879 阅读数 3546
  • 深度学习项目实战-对抗生成网络

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 对抗生成网络在16年爆火,成了深度学习圈子里的家常话。课程首先讲解对抗生成网络基本原理,通过案例演示原理和流程。后项目实战对抗生成网络的升级版DCGAN,大家都可以基于DCGAN生成出来任何你喜欢的数据。 课程代码基于Tensorflow框架,案例与项目课时会通过debug的形式详解代码中每行的用法。

    8232 人正在学习 去看看 唐宇迪
02-29 16:40:55.122 10369 11444 I ActivityManager: Recipient 28089
02-29 16:40:55.123 10369 11444 I ActivityManager: Process com.htc.android.mail:sync (pid 28089) has died
02-29 16:40:55.273 28357 28376 F libc    : Fatal signal 11 (SIGSEGV), code 1, fault addr 0x4417541a in tid 28376 (GLThread 2677)
02-29 16:40:55.301 10369 11615 I ActivityManager: Recipient 27511
02-29 16:40:55.302 10369 11615 I ActivityManager: Process com.htc.bgp (pid 27511) has died
02-29 16:40:55.325   643   643 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
02-29 16:40:55.325   643   643 F DEBUG   : Build fingerprint: 'htc/hiaetuhl_01405/htc_hiaetuhl:6.0/MRA58K/660257.25:user/release-keys'
02-29 16:40:55.325   643   643 F DEBUG   : Revision: '0'
02-29 16:40:55.325   643   643 F DEBUG   : ABI: 'arm'
02-29 16:40:55.325   643   643 F DEBUG   : pid: 28357, tid: 28376, name: GLThread 2677  >>> tw.mobage.g23000108 <<<
02-29 16:40:55.325   643   643 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4417541a
02-29 16:40:55.342   643   643 F DEBUG   :     r0 4417541a  r1 4417541a  r2 ffffffff  r3 00000006
02-29 16:40:55.342   643   643 F DEBUG   :     r4 00000002  r5 f3aa1958  r6 0ccccccc  r7 00000000
02-29 16:40:55.342   643   643 F DEBUG   :     r8 f3aa2294  r9 00000000  sl 4417541a  fp f3aa2298
02-29 16:40:55.342   643   643 F DEBUG   :     ip 00000002  sp f3aa1850  lr f6da9411  pc f6d84030  cpsr 200f0030
02-29 16:40:55.345   643   643 F DEBUG   : 
02-29 16:40:55.345   643   643 F DEBUG   : backtrace:
02-29 16:40:55.345   643   643 F DEBUG   :     #00 pc 00018030  /system/lib/libc.so (strlen+35)
02-29 16:40:55.345   643   643 F DEBUG   :     #01 pc 0003d40d  /system/lib/libc.so (__vfprintf+2948)
02-29 16:40:55.345   643   643 F DEBUG   :     #02 pc 0004080d  /system/lib/libc.so (vsnprintf+124)
02-29 16:40:55.345   643   643 F DEBUG   :     #03 pc 0000305f  /system/lib/liblog.so (__android_log_print+42)
02-29 16:40:55.345   643   643 F DEBUG   :     #04 pc 001f29a3  /data/app/tw.mobage.g23000108-1/lib/arm/libjinqu.so (cocos2d::CCLog(char const*, ...)+50)
02-29 16:40:55.345   643   643 F DEBUG   :     #05 pc 002c13e7  /data/app/tw.mobage.g23000108-1/lib/arm/libjinqu.so
02-29 16:40:55.345   643   643 F DEBUG   :     #06 pc 003e1590  /data/app/tw.mobage.g23000108-1/lib/arm/libjinqu.so
02-29 16:40:55.345   643   643 F DEBUG   :     #07 pc 0042923c  /data/app/tw.mobage.g23000108-1/lib/arm/libjinqu.so
02-29 16:40:55.360 10369 10445 D PMS     : releaseHCC(960da24): CPU_MIN_NUM ActivityManager-MultiCore-Num 0x8000 null
02-29 16:40:55.360 10369 10445 D PMS     : releaseHCC(c8c098d): CPU_MIN_FREQ ActivityManager-MultiCore-Freq 0x2000 null
02-29 16:40:55.770   643   643 F DEBUG   : 
02-29 16:40:55.770   643   643 F DEBUG   : Tombstone written to: /data/tombstones/tombstone_09
02-29 16:40:55.770 10369 10429 I BootReceiver: Copying /data/tombstones/tombstone_09 to DropBox (SYSTEM_TOMBSTONE)

02-29 16:40:55.774 10369 28468 W ActivityManager:   Force finishing activity tw.mobage.g23000108/www.kaiqigu.transformer.Transformer


以上是问题打印的log,很明显问题出在CCLOG上。

经过多方排查 和询问 最终发现 是之前在打包时把DEBUG模式开启了。在6.0上cclog出问题了。将DEBUG模式关闭即可

路径: /Users/mars_macpro/transform_client/projects/transformer_taiwan/proj.android/jni/Application.mk :

内容:

NDK_TOOLCHAIN_VERSION=4.8
APP_ABI := armeabi x86
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -DPLATFORM_NONE -DCOCOS2D_DEBUG=1
APP_CFLAGS += -Wno-error=format-security
APP_CPPFLAGS += -std=c++11

修改:

将最后一个1改为0即可关闭。


说明一下libjinqu.so文件。

这个文件是讲c++的东西封存成一个so文件。


这个问题我查了一下午,本身也不是很熟悉。这下熟悉了。都是以前自己给自己买下的坑,忘记改回去。

没有更多推荐了,返回首页