【问题标题】:Method work right when deploy via Debugger but same method not working when APK is exported通过调试器部署时方法正常工作,但导出 APK 时相同方法不工作
【发布时间】:2020-07-16 18:48:32
【问题描述】:

部署在 Xamarin.Android 中制作的 APK 时出现此错误(来自我设备的 Logcat)

>*android.runtime.JavaProxyThrowable: System.NullReferenceException: Object reference not set to an instance of an object
  at MyApp.InvoiceActivity.SendJson (System.String Json, System.String Route, System.String Token) [0x00053] in <f72bff8dbb074291a532e12425c8737a>:0 
  at MyApp.InvoiceActivity.OnCreate (Android.OS.Bundle bundle) [0x0004a] in <f72bff8dbb074291a532e12425c8737a>:0 
  at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x0000f] in <0181fdcaff164e668b24279eb4fb429f>:0 
  at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.1(intptr,intptr,intptr)
    at crc64df67992c1ed0ef67.InvoiceActivity.n_onCreate(Native Method)
    at crc64df67992c1ed0ef67.InvoiceActivity.onCreate(Unknown Source:0)
    at android.app.Activity.performCreate(Activity.java:7136)
    at android.app.Activity.performCreate(Activity.java:7127)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6669)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)*

这个错误说明我的问题是从 sendJson() 方法开始的,这是这个方法的 sn-p

public string SendJson(string Json, string Route = "MyRoute", string Token = "MyToken")
{
     try
     {
         using var client = new WebClient();
         client.Headers[HttpRequestHeader.ContentType] = "application/json";
         client.Headers[HttpRequestHeader.Authorization] = "Token token=" + Token;

         string response = client.UploadString(Route, "POST", Json);
         return response;
     }
     catch (WebException ex)
     {
          var response = new StreamReader(ex.Response.GetResponseStream()).ReadToEnd();

          return response;
     }
} 

但是,此错误仅在从导出的 APK 安装和执行应用时发生。当我使用 Visual Studio 调试器时,该方法运行良好。

我尝试将方法放在隔离类或 Activity 中(甚至将部分方法放在 onCreate() 方法中),更改级别访问,但没有任何效果。

编辑

感谢大家的回答,并给我一些关于这个问题的想法。进行一些测试后,我发现在项目属性的编译部分启用“优化代码”时会出现问题。在 Xamarin.Android 中,要导出已签名的 APK,您需要首先将项目设置为“发布”模式,当然,默认情况下会启用此选项。我不确定这是编译器的错误还是只是我的错,所以我会继续调查:)。无论如何,再次感谢您的帮助。

【问题讨论】:

  • 空引用异常可能来自您的异常处理程序;我不知道。分而治之,你应该很容易找到它。此外,您可能应该编辑您的帖子以不包含您的代码两次。
  • 感谢您的回答。即使没有 try-catch,我也尝试了该方法,结果是相同的:通过 Debugger 部署应用程序效果很好,但是当导出 APK 方法不起作用并且我的应用程序因错误而崩溃(在问题开始时描述)。发布我的代码是为了了解我想要做什么。对不起我的英语。
  • 欢迎来到 SO !你可以试试async/await方法使用WebClient。然后检查是否可以收到响应。
  • 感谢小辈的回答。我试过这个方法,当然效果很好,我会投入我的项目中,非常感谢你的想法。但是,问题仍然存在。进行一些测试后,我发现:启用项目编译部分中的“优化代码”时,我的应用程序崩溃。所以,我禁用了它,它就像一个魅力。有点好奇,因为从未见过。

标签: c# rest xamarin xamarin.android


【解决方案1】:

最后问题是一样的:应用程序在调试中工作,而在发布时(特别是在导出的 apk 中)应用程序不起作用。经过一番挖掘,我发现发生这种情况是因为通过调试的 AndroidManifest 拥有所有权限。在导出 apk 之前,我们需要通过(在我的情况下)VisualStudio 明确设置所需的权限。例如,在我的应用程序中,需要 Internet 连接来执行一些 API 调用和文件访问以存储返回的数据(文件或数据库上的数据持久性),这意味着我们需要在我们的“真实”AndroidManifest 中使用 ACCESS_NETWORK_STATE 和 WRITE_EXTERNAL_STORAGE,因此将权限设置为AndroidManifest 和...应用仍然无法正常工作。

在 API 调用代码中获取 Saamer 答案的一部分会引发异常:无法访问服务器。由于某种原因,该应用程序基本上无法连接到服务器。一开始并不清楚,从 WebClient 切换到 RestSharp 会引发代码 0(无或无连接)。考虑到这一点,在 Xamarin 文档中找到了答案:默认情况下支持和允许的权限 (https://docs.microsoft.com/en-us/xamarin/essentials/permissions?context=xamarin%2Fandroid&tabs=android)。因此,需要请求 ACCESS_NETWORK_STATE 和 WRITE_EXTERNAL_STORAGE,因为我们的 AndroidManifest 中默认不允许。我知道这是一个可怕的错误,但这是我的第一个应用程序,所以也许这可以帮助其他面临类似情况的人。感谢您的帮助。

【讨论】:

    【解决方案2】:

    分析错误来源:

    根据 LogCat,您收到错误是因为 SendJson 函数中的一些代码。 但唯一可能导致问题的代码是这一行:

    var response = new StreamReader(ex.Response.GetResponseStream()).ReadToEnd();
    

    那是因为其余代码在 try 的帮助下实现了错误处理。但是,上面的行没有任何 try-catch 来捕获代码引发的异常。

    解决问题:

    正确的解决方法是从一开始就防止错误发生。

    • 您正在使用 httpclient incorrectly 的 using 语句。您可能希望改用静态 httpclient,如 Official Microsoft Documentation 所示。
    • 您似乎遇到了这个问题,因为您没有使用异步调用,所以您的客户端结果为空。
    • 您的 try-catch 似乎捕捉到了该错误,但是您的“GetResponseStream() 也是空的。因此您的应用程序尝试 ReadToEnd() 获取空对象。这会导致您的崩溃。所以摆脱它,而是只需使用通用异常catch (Exception ex),这样您就可以返回收到的错误消息。 您可以执行以下操作:
    static HttpClient client = new HttpClient();
    public Task<string> SendJsonAsync(string Json, string Route = "MyRoute", string Token = "MyToken")
    {
         try
         {
             client.Headers[HttpRequestHeader.ContentType] = "application/json";
             client.Headers[HttpRequestHeader.Authorization] = "Token token=" + Token;
    
             string response = await client.UploadStringAsync(Route, "POST", Json);
             return response;
         }
         catch (Exception ex)
         {
              var response = ex.Message;
              return response;
         }
    } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-03
      • 2021-07-19
      • 1970-01-01
      • 2016-03-06
      • 2021-11-23
      • 2021-10-24
      相关资源
      最近更新 更多