当前位置: 首页 > 知识库问答 >
问题:

Codename One -获取Android和iOS原生日志的原生代码

魏旭
2023-03-14

读者更新:此处讨论的代码现在在此代号 One 库中可用(它也在 CN1 扩展管理器中...):https://github.com/jsfan3/CN1Libs-NativeLogsReader

简短的问题:

我编写了一个有效的本机Android代码,以便在执行我的Codename One应用程序期间获取设备的本机日志。我使用了代号一提供的本机接口功能。我需要帮助才能为iOS实现此接口。

长问题。。。

首先,当我在应用程序中遇到奇怪的行为时,我尝试获取原生日志(例如Android Studio和XCode提供的日志)以寻求帮助......因为标准的Codename One日志在某些情况下是不够的(例如,我遇到了使用Google Maps CN1Lib等原生组件的问题)。

我是Android Studio的新手,我在获取我的Codename One应用程序的Logcat时遇到了麻烦,我也很难使用构建服务器提供的原生源代码。此外,我没有苹果电脑,所以我不能使用XCode。

我的语言技能仅限于代号1Java8,我不会“说”Android原生Java我觉得iOS原生Objective-C不可读...

这就是为什么,为了帮助自己在需要在Codename One的Github存储库中提交一些问题时提供准确的日志,我尝试编写本机代码,以字符串形式获取本机日志(我可以用几种简单的方式来管理,例如,我可以将其显示在表单中,然后通过电子邮件发送给自己)。

所以…我能够实现Android的代码:它工作得很好。我在几个Android版本中进行了测试。

CallNativeCode.java

package ...;

import com.codename1.system.NativeInterface;

/**
 * Native Code interface
 */
public interface CallNativeCode extends NativeInterface {

    public void clearAndRestartLog();
    public String readLog();
    public String getFilePath();

}

CallNativeCodeImpl.java

package ...;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class CallNativeCodeImpl {

    public String getFilePath() {
        return null;
    }

    public void clearAndRestartLog() {
        // https://developer.android.com/studio/command-line/logcat
        try {
            Runtime.getRuntime().exec("logcat -b all -c");
            Runtime.getRuntime().exec("logcat");
        } catch (IOException ex) {
            // logcat non available?
        }
    }

    // original code: https://stackoverflow.com/q/12692103
    public String readLog() {
        try {
            Process process = Runtime.getRuntime().exec("logcat -d");
            BufferedReader bufferedReader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()));

            StringBuilder log = new StringBuilder();
            String line = "";
            while ((line = bufferedReader.readLine()) != null) {
                log.append(line);
                log.append("\n");
            }
            return log.toString();
        } catch (IOException e) {
            return "Log is not available.";
        }
    }

    public boolean isSupported() {
        return true;
    }

}

它是这样工作的:在Codename One app的主类的init()中我添加了:

// Test of Native code
        CallNativeCode callNativeCode = NativeLookup.create(CallNativeCode.class);
        if (callNativeCode != null && callNativeCode.isSupported()) {
            Log.p("Native code can be executed");
            callNativeCode.clearAndRestartLog();
            Log.p("Native LOG cleared and restarted");
        } else {
            Log.p("Native code cannot be executed");
        }

然后,当我想获取应用程序的本机日志时,我可以执行:

String nativeLog = callNativeCode.readLog();

通过这种方式,我获得了相同的Android Studio Logcat输出,而无需使用Android Studio,也无需连接到计算机的设备。

我试图为iOS复制这个功能...但是我遇到了麻烦,因为我不知道Objective-C。我试图将本机输出日志重定向到一个文件,然后读取该文件(调整我找到的一些代码并试图猜测它是如何工作的)...但是我不确定如何做到这一点,我的代码不能在iOS构建服务器上编译。

下面的代码是我尝试做的。如何修复?谢谢

myPackageName_CallNativeCodeImpl.h

#import <Foundation/Foundation.h>

@interface cool_teammate_registration_CallNativeCodeImpl : NSObject {
}

-(NSString*)readLog;
-(NSString*)getFilePath;
-(void)clearAndRestartLog;
-(BOOL)isSupported;
@end

my package name _ callnativecodeimpl . m

#import "myPackageName_CallNativeCodeImpl.h"

@implementation myPackageName_CallNativeCodeImpl

-(NSString*)getFilePath{
    NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
    NSString* documentsDirectory = [paths objectAtIndex:0];
    NSString* fileName =[NSString stringWithFormat:@"%@.log",[NSDate date]];
    NSString* logFilePath = [documentsDirectory stringByAppendingPathComponent:fileName];
    return logFilePath;
}

-(NSString)readLog{
    NSString* logFilePath = [self getFilePath];
    NSString* content = [NSString stringWithContentsOfFile:logFilePath encoding:NSUTF8StringEncoding error:nil];
    return content;
}

-(void)clearAndRestartLog{
    // https://stackoverflow.com/questions/5179108/iphone-how-to-read-application-logs-from-device
    NSString* logFilePath = [self getFilePath];
    freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
}

-(BOOL)isSupported{
    return YES;
}

@end

共有1个答案

吴均
2023-03-14

我的iOS代码中有一个打字错误(< code>NSString而不是< code > ns string * )。

我在这篇文章中找到了有用的信息:将iOS错误记录到文件中。我用这些信息对代码进行了小优化。

最后,这是我的工作代码(在iOS 8、iOS 9、iOS 10、iOS 11上测试成功)。这样,我就可以获取控制台日志,而不需要将设备连接到安装了XCode的Mac上:)

my package name _ callnativecodeimpl . m

#import "myPackageName_CallNativeCodeImpl.h"

@implementation myPackageName_CallNativeCodeImpl

// Useful information:
// Log iOS Errors to File
// https://www.progressconcepts.com/blog/log-ios-errors-file/

-(NSString*)getFilePath{
    NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
    NSString* documentsDirectory = [paths objectAtIndex:0];
    NSString* fileName = @"device.log";
    NSString* logFilePath = [documentsDirectory stringByAppendingPathComponent:fileName];
    return logFilePath;
}

-(NSString*)readLog{
    NSString* logFilePath = [self getFilePath];
    NSString* content = [NSString stringWithContentsOfFile:logFilePath encoding:NSUTF8StringEncoding error:nil];
    return content;
}

-(void)clearAndRestartLog{
    NSError *error = nil;
    NSString* logFilePath = [self getFilePath];
    [[NSFileManager defaultManager] removeItemAtPath:logFilePath error:&error];

    // wrap the code to check if the debugger was attached, and only write to the file when it wasn’t
    if (!isatty(STDERR_FILENO)) { 
        freopen([logFilePath cStringUsingEncoding:NSUTF8StringEncoding],"a+",stdout);
        freopen([logFilePath cStringUsingEncoding:NSUTF8StringEncoding],"a+",stderr);
    }
}

-(BOOL)isSupported{
    return YES;
}

@end
 类似资料:
  • 每次我重新打开项目和模拟器时,我都必须在命令提示符中运行和吗? 谢谢。

  • 我的工作区布局为: 如何在Eclipse中调试原生库?有人对此有所暗示吗?

  • 返回值的原生类型。 返回值小写的构造函数名称,如果值为 undefined 或 null ,则返回 "undefined" 或 "null"。 const getType = v => v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase(); getType(new Set(

  • 本文向大家介绍Android中js和原生交互的示例代码,包括了Android中js和原生交互的示例代码的使用技巧和注意事项,需要的朋友参考一下 本文介绍了Android中js和原生交互的示例代码,分享给大家,具体如下: 加载webview的类 JavaScriptInterface类 webview 代码下载 Demo代码下载(AS导到Module里) 以上就是本文的全部内容,希望对大家的学习有所

  • "prototype" 属性在 JavaScript 自身的核心部分中被广泛地应用。所有的内置构造函数都用到了它。 首先,我们将看看原生原型的详细信息,然后学习如何使用它为内建对象添加新功能。 Object.prototype 假如我们输出一个空对象: let obj = {}; alert( obj ); // "[object Object]" ? 生成字符串 "[object Object]

  • 本文向大家介绍ios原生和react-native各种交互的示例代码,包括了ios原生和react-native各种交互的示例代码的使用技巧和注意事项,需要的朋友参考一下 需求:让一个表格视图中的cell能左滑删除,效果图如下: 目前RN中的ListView主要问题是复用,以及其他一些细节如索引视图、左滑删除、编辑等,要想在RN上自定义实现原生的这种效果尚有一定的问题,在必要时可以考虑使用原生的U