从App Store下载时,为什么应用程序无法正常工作 [英] Why does app work incorrectly when downloaded from App Store.

查看:120
本文介绍了从App Store下载时,为什么应用程序无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经和这个人打了几个星期,但没有运气。希望你能帮忙。我也在尝试Apple开发人员支持和Xamarin。





  • 此应用程序最初是针对iOS编写的< 6。它在商店里。 有效
  • 我最近为iOS 7兼容性更新了它。我在模拟器,iPad3和iPhone 3GS上进行了测试;在Debug和Release中;我将它上传到Testflight并从那里安装。 所有组合都运行良好
  • 我将其上传到App Store。它被批准了。 它不起作用。
  • I've been fighting this one for a few weeks, and haven't had any luck. Hope you might be able to help. I'm also trying Apple Developer Support and Xamarin.


    • This app, originally writted for iOS <6. It was in the store. It worked.
    • I recently updated it for iOS 7 compatibility. I tested it in the simulator, on an iPad3, on an iPhone 3GS; in Debug and Release; I uploaded it to Testflight and installed it from there. All combinations worked fine.
    • I uploaded it to the App Store. It was approved. It doesn't work.
    • var handshake = new HandshakeController ();
      handshake.Handshake();
      



      它试图获取此客户端设备的服务器ID。


      It tries to get the server's id for this client device.

      /// <summary>
      /// Handshakes with the server.
      /// </summary>
      public void Handshake()
      {
          XDocument ourSettings=null, theirSettings=null;
      
          // Get (or create) a unique device ID.
          Globals.DeviceId = GetDeviceId ();
          if(Globals.DeviceId == null)
              throw new ApplicationException("Network and databases unavailable");
          ...snip...
      }
      



      这是第一次运行,所以它需要一个新的ID


      This is the first time it is being run, so it needs a new ID

      /// <summary>
      /// Gets the device identifier.
      /// </summary>
      /// <returns>
      /// The device identifier.
      /// </returns>
      private string GetDeviceId()
      {
          return GetLocalDeviceId() ?? GetNewDeviceId();
      }
      



      这就是我们的工作。


      So that's what we do.

      /// <summary>
      /// Gets a new device identifier.
      /// </summary>
      /// <returns>
      /// The new device identifier.
      /// </returns>
      private string GetNewDeviceId()
      {
          var client = new TourismClient();
          var id = client.Handshake("iOS", Globals.Hardware.GetVersion().ToString());
      
          ...snip...
      }
      



      特定于应用的请求...


      The app-specific request ...

      /// <summary>
      /// Initializes a new session.
      /// </summary>
      /// <param name="platform"></param>
      /// <returns>
      /// A unique id.
      /// </returns>
      public string Handshake(string platform, string hardware)
      {
          return base.Request<string, string, string>("Handshake", platform, hardware);
      }
      



      ...调用更通用的抽象请求...


      ... calls an even more generic abstracted request ...

      /// <summary>
      /// Calls a WebMethod and returns the results.
      /// </summary>
      /// <typeparam name="T">The type to be returned.</typeparam>
      /// <typeparam name="U">The type of the first parameter.</typeparam>
      /// <typeparam name="V">The type of the second parameter.</typeparam>
      /// <param name="methodName">Name of the method.</param>
      /// <param name="param1">The first parameter.</param>
      /// <param name="param2">The second parameter.</param>
      /// <returns>The result of the request.</returns>
      protected T Request<T, U, V>(string methodName, U param1, V param2)
      {
          return Request<T>(methodName, new [] { typeof(U), typeof(V) }, new object[] { param1, param2 });
      }
      



      ...调用执行脏工作的方法...


      ... that calls the method that does the dirty work...

          /// <summary>
          /// Calls a WebMethod and returns the results.
          /// </summary>
          /// <typeparam name="T"></typeparam>
          /// <param name="methodName">Name of the method.</param>
          /// <param name="parameterTypes">The parameter types.</param>
          /// <param name="parameters">The parameters.</param>
          /// <returns>The result of the request.</returns>
          /// <exception cref="XmlException">An XmlException occured while parsing an XML document returned by the web service.</exception>
          /// <exception cref="InvalidCastException">The data returned by the web service cannot be converted to the return type.</exception>
          private T Request<T>(string methodName, Type[] parameterTypes, IList<object> parameters)
          {
              // Sanity check.
              if (parameterTypes.Length != parameters.Count)
                  throw new RestException(400, "Bad Request", "Parameter counts do not match.");
      
              // Get the Contract. This class inherits from it and it has a WebServiceAttribute.
              var contract = (from I in GetType().GetInterfaces()
                              where I.GetCustomAttributes(typeof(WebServiceAttribute), false).Length == 1
                              select I).FirstOrDefault();
              if(contract == null)
                  throw new RestException(500, "Server Error", "The proxy client does not implement a contract.");
      
              // Get the Method
              var method = contract.GetMethod(methodName, parameterTypes);
              if(method == null)
                  throw new Exception(methodName);
          ...snip...
      }
      



      此时,REST客户端会进行一些检查。使用它的类是实现接口所必需的。它确实如此,这是界面中适用的行:


      At this point the REST client does some checks. Classes that use it are required to implement an interface. It does, and this is the line in the interface that is applicable:

      /// <summary>
      /// Initializes a new session.
      /// </summary>
      /// <param name="platform">The platform.</param>
      /// <param name="hardware">The hardware.</param>
      /// <returns>
      /// A unique id.
      /// </returns>
      [HttpMethod(HttpMethods.Get)]
      [WebMethod("Initializes a new session.")]
      [HttpCredentials(false)]
      string Handshake(string platform, string hardware);
      



      返回Request方法,使用反射找到界面。现在关键部分:


      Back to the Request method, the interface is found using reflection. Now the critical part:

      // Get the Method
      var method = contract.GetMethod(methodName, parameterTypes);
      if(method == null)
          throw new Exception(methodName);
      



      在所有情况下,除了从App Store安装应用程序之外,此测试通过,REST客户端继续构建和调用HTTP GET请求,生活还在继续。



      从App Store安装时,此测试失败。我抛出新的异常(握手),被捕获和处理。



      总神秘。



      注意:这里使用的REST客户端/服务器代码是我近8年前编写的,在生产环境中有很多应用程序。虽然我可能错过了一个错误,但是有点怀疑。



      用另一种方式描述问题,当REST客户端使用反射检查时有问题的方法的存在,它不应该失败,因为如果该方法不存在,应用程序将无法编译,因为该方法是在接口和行


      In all cases, except when the app is installed from the App Store, this test passes, and the REST client goes on to build and invoke an HTTP GET request, and life goes on.

      When installed from the App Store, this test fails. I throws new Exception("Handshake"), which is caught and handled.

      Total mystery.

      Note: the REST client/server code used here was written by me close to 8 years ago and is in dozens of applications in production environments. While it is possible that I missed a bug, a doubt it.

      To describe the problem another way, when the REST client uses reflection to check for the existence of the method in question, it should not be possible to fail, because if that method was not present the application would not compile, since that method is defined in the interface and the line

      public string Handshake(string platform, string hardware)<br />

      实现合同。



      我不认为错误在哪里错了正在发生,因为(a)这是唯一的 throw ,它发送方法名称,并报告给UI; (b)几行之后调用网络请求,并且应用程序根本没有网络活动。方法名称检查和网络调用之间的唯一代码是:

      implements the contract.

      I don't think I am wrong about where the error is occurring, because (a) this is the only throw that sends the method name, which is reported to the UI; (b) a few lines later the network request is invoked, and there is not network activity by the app at all. The only code between the method name check and the network call is:

      // Get the HttpMethod.
       var httpMethodAttribute = method.GetCustomAttributes(typeof(HttpMethodAttribute), false).FirstOrDefault() as HttpMethodAttribute;
       var httpMethod = httpMethodAttribute == null ? HttpMethods.Get : httpMethodAttribute.Value;
      
       // Build the query string.
       var queryString = "";
       var methodParameters = method.GetParameters();
       for (var j = 0; j < methodParameters.Length; j++)
           queryString += (j == 0 ? "" : "&") + methodParameters[j].Name + "=" + HttpUtility.UrlEncode(parameters[j] == null ? string.Empty : parameters[j].ToString());
      
       // Build the request
       Uri uri;
       if (httpMethod == HttpMethods.Get || httpMethod == HttpMethods.Put || httpMethod == HttpMethods.Delete)
           uri = new Uri(_baseUri, methodName + "?" + queryString);
       else
           uri = new Uri(_baseUri, methodName);
       var request = WebRequest.Create(uri) as HttpWebRequest;
       request.Method = httpMethod.ToString().ToUpper();
       request.UserAgent = GetType().AssemblyQualifiedName;
       request.Accept = "*/*";
      
       if (httpMethod == HttpMethods.Post)
       {
           request.ContentType = "application/x-www-form-urlencoded";
           var queryStringBytes = Encoding.UTF8.GetBytes(queryString);
           request.ContentLength = queryStringBytes.Length;
           using(var requestStream = request.GetRequestStream())
               requestStream.Write(queryStringBytes, 0, queryStringBytes.Length);
       }
      
       if (Credentials != null)
       {
           request.Credentials = Credentials;
           request.PreAuthenticate = true;
       }
      
       // Submit the request and get the response data
       HttpWebResponse response;
       try { response = request.GetResponse() as HttpWebResponse; }
       catch(WebException we) { response = we.Response as HttpWebResponse; }
      



      并且没有一个会抛出异常消息是Handshake。



      主要是,我该如何调试?由于涉及到应用商店,一个调试周期大约需要一周。



      我想我可以越狱设备,使用AppStore配置文件进行编译,并尝试调试方式。



      现在我想我会尝试将调试器附加到应用程序商店版本,看看我是否可以单步执行CIL btyecode来查找内容。< br $> b $ b

      如果我很幸运,我会错过一些明显的东西,你会告诉我。


      and none of that would throw an exception where the message is "Handshake".

      The main thing is, how do I debug this? Since the app store is involved, one debug cycle takes about a week.

      I guess I could jailbreak the device, compile using the AppStore profile, and try to debug that way.

      For now I guess I'll try to attach a debugger to the app store version and see if I can step through CIL btyecode to find what's up.

      Or if I'm lucky, I missed something obvious and you'll tell me.

      推荐答案

      几周后我发现了它。我比较了Release和AppStore版本的csproj部分,AppStore还有额外的一行:

      After many weeks I found it. I compared the csproj sections of Release and AppStore builds, and the AppStore had the additional line:
      <mtouchlink>Full</mtouchlink>



      由于我的应用已使用反射调用RESTful客户端库,链接器认为我不需要某些功能并对其进行优化。


      Since my app uses reflection to invoke the RESTful client library, the linker did not think I needed certain functionality and optimized it away.


      这篇关于从App Store下载时,为什么应用程序无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆