代号一-本机代码获取Android和iOS的本机日志

弗朗切斯科·加尔加尼(Francesco Galgani)

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


简短问题:

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

长问题...

首先,我尝试获取本机日志(例如Android Studio和XCode提供的日志以在我的应用中出现异常行为时寻求帮助...因为标准Codename One日志在几种情况下还不够(例如,我在使用Google Maps CN1Lib等本地组件时遇到了问题。

我是Android Studio的新手,我在获取Codename One应用程序的Logcat时遇到了麻烦,而且在使用构建服务器提供的本机源方面也遇到了很大的困难。而且,我还没有Mac,因此无法使用XCode。

我的语言技能仅限于Codename One Java 8,我不会“讲” Android本机Java,而我感觉iOS本机Objective-C是不可读的...

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

所以...我能够实现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应用主类的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,也无需将设备连接到计算机,即可获得与Android Studio Logcat相同的输出。

我试图为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

myPackageName_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
弗朗切斯科·加尔加尼(Francesco Galgani)

我的iOS代码(NSString而不是NSStrings*)中出现输入错误

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

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

myPackageName_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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章