앱을 배포했는데 12.0 버전에서 실행시 오류가 발생해서 반려?가되었다.

iOS 는 신규 버전이 나오면 거기까지 테스트를 해야하는구나;;;

그래도 다행인건 iOS xcode 버전을 올리고

윈도우에서 Visual Studio 를 실행하니 알아서 iOS 의 Xamarin.iOS 도 업데이트 해준다.

 

방법은 아래 링크에 자세히 나와있다.

https://docs.microsoft.com/ko-kr/xamarin/xamarin-forms/platform/wpf

 

주의할 점

1. 프레임워크 대상 버전이 4.7 이상이어야한다.

2. MainWindow.xaml 내용의 처음을 Window -> wpf:FormsApplicationPage 으로 변경해야한다.

3. MainWindow.xaml.cs 에서 상속을 FormsApplicationPage 으로 변경해야한다.

4. 링크에도 나와있듯이 WPF 프로젝트에 설치한 Xamarin.Forms 의 버전과 다른 프로젝트들과 버전을 맞춰야한다.

 

아래는 기본 자마린 솔루션에서 WPF 프로젝트만 추가한 내용이다.

XamarinStudy.z01

XamarinStudy.z02

XamarinStudy.zip

 

아래는 실행한 WPF 결과

 

WebView 에서 JavaScript 실행은 간단히 아래와 같히 펑션을 호출하면 된다.

this.webView.Eval("TestFunction()");

 

하지만 리턴이 있는 JavaSecript funtion 실행결과는 저 형태로는 안된다.

따로 Renderer 를 이용해 구현하는 방법을 소개한다.

 

먼저 .Net Standard 프로젝트에 아래와 같이 WebViewer 를 만든다.

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace Test
{
    public class WebViewer : WebView
    {
        public static BindableProperty EvaluateJavascriptProperty =
        BindableProperty.Create(nameof(EvaluateJavascript), typeof(Func<string, Task<string>>), typeof(WebViewer), null, BindingMode.OneWayToSource);

        public Func<string, Task<string>> EvaluateJavascript
        {
            get { return (Func<string, Task<string>>)GetValue(EvaluateJavascriptProperty); }
            set { SetValue(EvaluateJavascriptProperty, value); }
        }
    }
}

이제 위 항목을 상속받아서 각 기기별로 Renderer 를 생성하자.

 

Android

using System;
using System.Threading;
using System.Threading.Tasks;
using Android.Content;
using Android.Webkit;
using Test;
using Test.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(WebViewer), typeof(WebViewRender))]
namespace Test.Droid
{
    public class WebViewRender : WebViewRenderer
    {
        public WebViewRender(Context context) : base(context)
        { }

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
        {
            base.OnElementChanged(e);

            if (e.NewElement is WebViewer webView)
            {
                webView.EvaluateJavascript = async (js) =>
                {
                    var reset = new ManualResetEvent(false);
                    var response = string.Empty;
                    Device.BeginInvokeOnMainThread(() =>
                    {
                        Control?.EvaluateJavascript(js, new JavascriptCallback((r) => { response = r; reset.Set(); }));
                    });
                    await Task.Run(() => { reset.WaitOne(); });
                    return response;
                };
            }
        }
    }

    internal class JavascriptCallback : Java.Lang.Object, IValueCallback
    {
        public JavascriptCallback(Action<string> callback)
        {
            _callback = callback;
        }

        private Action<string> _callback;
        public void OnReceiveValue(Java.Lang.Object value)
        {
            _callback?.Invoke(Convert.ToString(value));
        }
    }
}

 

iOS

using System.Threading.Tasks;
using Test;
using Test.iOS;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(WebViewer), typeof(WebViewRender))]
namespace Test.iOS
{
    public class WebViewRender : WebViewRenderer
    {
        protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);

            if (e.NewElement is WebViewer webView)
            {
                webView.EvaluateJavascript = (js) =>
                {
                    return Task.FromResult(this.EvaluateJavascript(js));
                };
            }
        }
    }
}

 

UWP

using System;
using Test;
using Test.UWP;
using Xamarin.Forms;
using Xamarin.Forms.Platform.UWP;

[assembly: ExportRenderer(typeof(WebViewer), typeof(WebViewRender))]
namespace Test.UWP
{
    public class WebViewRender : WebViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
        {
            base.OnElementChanged(e);
            if (e.NewElement is WebViewer webView)
            {
                webView.EvaluateJavascript = async (js) =>
                {
                    return await Control.InvokeScriptAsync("eval", new[] { js });
                };
            }
        }
    }
}

 

이제 화면에서 아래와 같이 컨트롤을 넣고

<test:WebViewer x:Name="webView" HorizontalOptions="FillAndExpand"  VerticalOptions="FillAndExpand"/>

아래와 같이 코딩하면 function 의 결과 값을 받아올수 있다.

var result = await this.webView.EvaluateJavascript("GetTest();");

 

SMSConvey 어플을 좀 업그레이드 하려고 하는데 갑자기 아래와 같은 에러가 났다.

Detected problems with app native libraries(please consult log for details): libmonosgen-64bit-2.0.so: unauthorized access to "/system/lib64/libsqlite.so"

오레오 업데이트 하고 나서 에러가 발생된것 같은데

찾아보니 7.0 부터 발생한 내용이라고 하던데.. 일단 내가 7.0 일때 테스트 할때는 저런 에러가 발생되지 않았다.

SQLite 사용시 발생되는 에러로 해결방법은

Nuget 패키지 관리자에서 "sqlite-net" 을 제거하고 "sqlite-net-pcl" 을 설치하면 된다.

 

**추가 (아래 방식으로 완전히 해결됨)

아래와 같이 package 를 설치하고

 

아래 두파일을 삭제합니다.

 

 

참고

https://forums.xamarin.com/discussion/78234/android-libmonosgen-library-sqlite-problems-with-app-native-libraries

앱상에서 권한을 준항목들이

오레오 버전 부터는 몇몇 특정 권한들이 권한이 빠지고 다시 사용자에게 권한허용을 받아야합니다.

만약 오레오 이전 버전에 잘 동작하던게 오레오 버전에서 동작하지 않는다면

권한으로 인해 먼가 동작하지 않는지 의심해 봐야합니다.

아래는 Xamarin.Android 에서 권한을 체크하고 권한이 없는 항목에 대해서

권한 허용을 요청하는 코드입니다.

(제가 문제가 되었던 권한는 android.permission.READ_SMS,  android.permission.WRITE_EXTERNAL_STORAGE,android.permission.SEND_SMS 입니다.)

// 권한이 없어 권한허용을 물어볼 항목들
List<string> permissions = new List<string>();

// 권한이 있는지 확인할 항목들
List<string> checkPermissions = new List<string>();
checkPermissions.Add(Manifest.Permission.AccessNetworkState);
checkPermissions.Add(Manifest.Permission.Internet);
checkPermissions.Add(Manifest.Permission.WriteSms);
checkPermissions.Add(Manifest.Permission.BroadcastSms);
checkPermissions.Add(Manifest.Permission.BroadcastWapPush);
checkPermissions.Add(Manifest.Permission.ReceiveBootCompleted);
checkPermissions.Add(Manifest.Permission.ReceiveMms);
checkPermissions.Add(Manifest.Permission.ReceiveSms);
checkPermissions.Add(Manifest.Permission.SendSms);
checkPermissions.Add(Manifest.Permission.WriteExternalStorage);
checkPermissions.Add(Manifest.Permission.ReadSms);

// 권한이 있는지 확인하고 없다면 체크할 목록에 추가합니다.
foreach (var checkPermission in checkPermissions)
{
    if (ContextCompat.CheckSelfPermission(this, checkPermission) != (int)Permission.Granted)
    {
        permissions.Add(checkPermission);
    }
}

// 권한없는 항목에 대해서 추가 허용을 할지 물어보는 팝업을 띄웁니다.
ActivityCompat.RequestPermissions(this, permissions.ToArray(), 1);

위 코드를 추가하면 앱 실행시 아래처럼 허용을 묻는 팝업이 뜹니다.

 

없던 권한이 3가지 인데 알아서 권한을 묶을수 있는것 들은 묶어서 팝업이 뜨는것 같네요

다시 말하지만 기존에 AndroidManifest.xml 에 권한이 포함되있더라도

오레오버전부터는 문제가 되는 권한들이 있으므로 위 작업이 필요합니다.

 

참고

https://developer.android.com/about/versions/oreo/android-8.0-changes?hl=ko

 

심각도 코드 설명 프로젝트 파일 줄 비표시 오류(Suppression) 상태
오류  /Users/mac/Library/Caches/Xamarin/mtbs/builds/MiGong.iOS/c10cbd8fd317519d3dd23b704514d419/bin/iPhone/Release/MiGong.iOS.app: errSecInternalComponent MiGong.iOS   

위과 같은 오류가 발생

mac 이 잠자기 모드이거나 로그인 활성화가 풀린경우 발생된다.

mac 으로 들어가 로그인하면 위 오류는 사라진다.

error MT1006: Could not install the application '/Users/mac/Library/Caches/Xamarin/mtbs/builds/MiGong.iOS/c10cbd8fd317519d3dd23b704514d419/bin/iPhone/Debug/MiGong.iOS.app' on the device 'Jun의 iPhone': AMDeviceSecureInstallApplicationBundle returned: 0xe8000087 (kAMDIncorrectArchitectureError).    0 

프로젝트 속성의 iOS 빌드 탭에서 지원되는 아키텍처를 ARM7+ARM64 으로 변경하면 오류가 해결된다.

 

 

심각도 코드 설명 프로젝트 파일 줄 비표시 오류(Suppression) 상태
오류  Can't write [C:\Users\kjun\AppData\Local\Temp\tad3j0pm.d2m.jar] (Can't read [C:\Users\kjun\AppData\Local\Xamarin\Xamarin.GooglePlayServices.Base\25.0.0\embedded\classes.jar(;;;;;;!META-INF/MANIFEST.MF)] (Duplicate zip entry [classes.jar:com/google/android/gms/common/annotation/KeepName.class])) MiGong.Android D:\[01]Source\KJunDev\MiGong\MiGong\MiGong.Android\CREATEMULTIDEXMAINDEXCLASSLIST  

갑자기 위와같은 에러가 발생되었다. nuget 패키지를 이것 저것 깔다 먼가 충돌이 발생해 지웠는데

저런 에러가.;;;

구글링 하니 이런 저런 방법이 있었는데 난 아래 처럼 하니 해결되었다.

도구>Android>Android SDK Manager 클릭

 

도구 탭에서 Google Play services 를 체크 해제하여 변경 내용 적용 을 하고

다시 체크하여 변경 내용 적용을 하여 재설치를 진행한다.

이러니 에러가 해결되었다.

 

아래 다른 방법.
https://forums.xamarin.com/discussion/55601/in-a-xamarin-android-project-how-can-i-remove-warnings-duplicate-zip-entry-classes-jar

네이버 아이디 로그인 후 아래와 같은 에러가 발생되었다.

디버그 모드에서는 발생안했던 에러가 릴리즈 모드에서 발생되었는데

원인은 인코딩 문제였다

 

Authentication Error e.Exception = Encoding 51949 data not be found...

 

iOS

Android

 

아래 그림과 같이 프로젝트 속성에서 인코딩에서 CJK 를 추가해야한다.

iOS (국제화)

Android (추가 지원 인코딩)

 

오류  Error loading '/Users/mac/Library/Caches/Xamarin/mtbs/builds/MiGong.iOS/c10cbd8fd317519d3dd23b704514d419/iTunesArtwork': Unknown image format. MiGong.iOS 

배포를 위해 빌드하는데 위와 같은 에러가 났다.

info.plist 의 iTunes 아트워크 부분의 이미지가 정상적이지 않아서 에러가 발생된다.

이미지를 크기를 맞춰 다시 넣어주면 정상적으로 동작한다.

근데 저게 머하는 놈이지;;;

+ Recent posts

티스토리 툴바