Syncfusion 의 SfRotator 는 아래 그림과 같이 이미지 등을 슬라이드로 보여주는 컨트롤입니다.

우선 보여줄 이미지를 준비합니다.

전 Images 폴더를 만들어 이미지를 넣었습니다.

이미지를 넣고 추가로 해야할건 각 이미지들의 속성에서 '빌드작업'을 '포함 리소스'로 변경해야합니다.

포함리소스 관련해서는 아래 포스팅 참고해주세요

2017/07/06 - [C#.NET/Xamarin] - (Xamarin Forms) 4.Image

 

이제 main1~5.jpg 그림파일을 5개를 이용해서 슬라이드 되도록 할것입니다.

우선  nuget 에서 SfRotator 를 검색해서 설치합니다.

 

아래처럼 xaml 파일을 작성합니다.

 

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:syncfusion="clr-namespace:Syncfusion.SfRotator.XForms;assembly=Syncfusion.SfRotator.XForms"
             x:Class="MiGong.HomePage">
    <ContentPage.Content>
        <StackLayout>
            <syncfusion:SfRotator x:Name="rotator" NavigationStripMode="Dots"  NavigationStripPosition="Bottom"
                                   EnableAutoPlay="true" NavigationDelay="3000"/>

            <Label Text="Welcome to Xamarin.Forms!"
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="CenterAndExpand" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

NavigationStripMode 는 네비게이션을 점으로 보일지 아니면 그냥 썸네일 방식으로 보여줄지 여부입니다.

NavigationStripPosition 은 네비게이션의 위치입니다.

EnableAutoPlay 는 자동으로 슬라이드가 될지 여부입니다.

NavigationDelay 는 자동으로 슬라이드되는 경우 정지될 시간입니다. (밀리초단위)

추가로 여러가지 속성이 있습니다.

아래 링크 참고해주세요

https://help.syncfusion.com/xamarin/sfrotator/overview

이제 비하인드 코드 xaml.cs 파일을 아래 처럼 작성합니다.

            List<SfRotatorItem> rotatorItem1 = new List<SfRotatorItem>();

            foreach (string imageName in new string[]{ "main1.jpg", "main2.jpg", "main3.jpg", "main4.jpg", "main5.jpg" })
            {
                SfRotatorItem item = new SfRotatorItem();
               
                Image image
                    = new Image()
                    {
                        Source = ImageSource.FromResource("MiGong.Images." + imageName),
                        Aspect = Aspect.AspectFill,
                        VerticalOptions = LayoutOptions.Center,
                        HeightRequest = 250
                        //WidthRequest = 400
                    };
               
                item.ItemContent = image;
                rotatorItem1.Add(item);
            }
            this.rotator.ItemsSource = rotatorItem1;

이제 실행해 보면 아래처럼 나타납니다.

 

 

 

이미지를 표현하는데 아래 처럼 에러가 발생되었다.

Unhandled Exception:

Java.Lang.OutOfMemoryError: Failed to allocate a 100712460 byte allocation with 16768736 free bytes and 55MB until OOM 발생

 

용량이 커서 그런가 했는데 1메가도 안된다.

무슨 문제인지 찾아보니 크기 문제였다.

크기를 조정하니 해결이 되었다.

다른 방법도 있는것 같다 아래 링크 참고..

https://stackoverflow.com/questions/32244851/androidjava-lang-outofmemoryerror-failed-to-allocate-a-23970828-byte-allocatio/32245018

 

 

 

 

 

우선 서버 만들기는 아래 포스팅을 참고한다.

2017/11/27 - [C#.NET/C#] - 카카오 쳇봇 만들기 - 2 (C# 서버 만들기)

2017/11/27 - [C#.NET/C#] - 카카오 쳇봇 만들기 - 3 (C# 서버 만들기)

 

서버쪽 코드

        #region PostUpLoadImage
        [Route("api/Files/Upload")]
        public async Task<string> PostUpLoadImage()
        {
            try
            {
                var httpRequest = HttpContext.Current.Request;

                if (httpRequest.Files.Count > 0)
                {
                    foreach (string file in httpRequest.Files)
                    {
                        var postedFile = httpRequest.Files[file];

                        var fileName = postedFile.FileName.Split('\\').LastOrDefault().Split('/').LastOrDefault();

                        var filePath = HttpContext.Current.Server.MapPath("~/Uploads/" + fileName);

                        postedFile.SaveAs(filePath);

                        return "/Uploads/" + fileName;
                    }
                }
            }
            catch (Exception exception)
            {
                return exception.Message;
            }

            return "no files";
        }
        #endregion

 

Xamarin Forms

Nuget 에서 Xam.Plugin.Media 설치

 

xaml 코드

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MiGong.TestPage">
    <ContentPage.Content>
        <StackLayout>
            <Label Text="File Upload"
           HorizontalOptions="Center" TextColor="Black" FontSize="20"/>

            <Button Text="Pick Photo"
            BackgroundColor="Teal" TextColor="White" FontSize="20" Clicked="PickPhoto_Clicked"/>

            <Button Text="Take Photo"
            BackgroundColor="Navy" TextColor="White" FontSize="20" Clicked="TakePhoto_Clicked"/>

            <Image x:Name="FileImage" WidthRequest="400" HeightRequest="220"/>

            <Label x:Name="LocalPathLabel" TextColor="Black" FontSize="18"/>

            <Button Text="Upload Photo"
            BackgroundColor="Purple" TextColor="White" FontSize="20" Clicked="UploadFile_Clicked"/>

            <Label x:Name="RemotePathLabel" FontSize="20" TextColor="Black"/>

        </StackLayout>
    </ContentPage.Content>
</ContentPage>

xaml.cs 코드 - 동작은 간단하다 파일을 선택하거나 카메라를 찍어서 서버에 해당 파일을 업로드한다.

[XamlCompilation(XamlCompilationOptions.Compile)]
 public partial class TestPage : ContentPage
 {
        private MediaFile _mediaFile;

        public TestPage ()
  {
   InitializeComponent ();
  }

        private async void PickPhoto_Clicked(object sender, EventArgs e)
        {
            await CrossMedia.Current.Initialize();

            if (!CrossMedia.Current.IsPickPhotoSupported)
            {
                await DisplayAlert("No PickPhoto", ":( No PickPhoto available.", "OK");
                return;
            }

            _mediaFile = await CrossMedia.Current.PickPhotoAsync();

            if (_mediaFile == null)
                return;

            LocalPathLabel.Text = _mediaFile.Path;

            FileImage.Source = ImageSource.FromStream(() =>
            {
                return _mediaFile.GetStream();
            });
        }

        private async void TakePhoto_Clicked(object sender, EventArgs e)
        {
            await CrossMedia.Current.Initialize();

            if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
            {
                await DisplayAlert("No Camera", ":( No camera available.", "OK");
                return;
            }

            _mediaFile = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
            {
                Directory = "Sample",
                Name = "myImage.jpg"
            });

            if (_mediaFile == null)
                return;

            LocalPathLabel.Text = _mediaFile.Path;

            FileImage.Source = ImageSource.FromStream(() =>
            {
                return _mediaFile.GetStream();
            });
        }

        private async void UploadFile_Clicked(object sender, EventArgs e)
        {
            var content = new MultipartFormDataContent();

            content.Add(new StreamContent(_mediaFile.GetStream()),
                "\"file\"",
                $"\"{_mediaFile.Path}\"");

            var httpClient = new HttpClient();

            var uploadServiceBaseAddress = "http://localhost:12214/api/Files/Upload";

            var httpResponseMessage = await httpClient.PostAsync(uploadServiceBaseAddress, content);

            RemotePathLabel.Text = await httpResponseMessage.Content.ReadAsStringAsync();
        }
    }

안드로이드쪽 MainActivity.cs 의 아래 굵은 부분 코딩 추가

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(bundle);

            CrossCurrentActivity.Current.Init(this, bundle);

            global::Xamarin.Forms.Forms.Init(this, bundle);
            LoadApplication(new App());
        }

        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults)
        {
            Plugin.Permissions.PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }

    }

AssemblyInfo.cs 파일에 아래 코드 추가

[assembly: UsesFeature("android.hardware.camera", Required = false)]
[assembly: UsesFeature("android.hardware.camera.autofocus", Required = false)]

매니패스트 권한을 부여한다.

 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 <uses-permission android:name="android.permission.CAMERA" />

서버쪽에 사이트 루트에 Uploads 폴더를 만든다.

위 까지 하면 파일 선택하여 업로드가 가능하다.

카메라를 사용하려면 좀더 설정이 필요하다.

AndroidManifest.xml 에 아래 내용추가

 <application ...">
    <provider android:name="android.support.v4.content.FileProvider"
          android:authorities="${applicationId}.fileprovider"
          android:exported="false"
          android:grantUriPermissions="true">

      <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"></meta-data>
    </provider>
  </application>

안드로이드 쪽 프로젝트에 아래 처럼 Resources 폴더 밑에 xml 폴더를 만들고 file_paths.xml  을 만들고

 

내용은 아래처럼 작성

<?xml version="1.0" encoding="utf-8" ?>
  <paths xmlns:android="http://schemas.android.com/apk/res/android">
<!--
    <external-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" />
    <external-path name="my_movies" path="Android/data/com.example.package.name/files/Movies" />
-->
   
    <external-files-path name="my_images" path="Pictures" />
    <external-files-path name="my_movies" path="Movies" />
  </paths>

 

추가 자세한 사항은 아래 링크를 참고

https://github.com/jamesmontemagno/MediaPlugin

 

https://www.c-sharpcorner.com/article/tabbed-page-in-xamarin-forms/

Async programming is all the rage in mobile app development for good reasons. Using async methods for long running tasks, like downloading data, helps keep your user interface responsive, while not using async methods, or the improper use of async/await, can cause your app’s UI to stop responding to user input until the long running task completes. This can result in a poor user experience, which can then lead to poor reviews on the app stores, which is never good for business.

Today we’ll take a look at the use of async and how to utilize it to prevent jerky and unexpected behaviors in a ListView.

What is async/await?

The async and await keywords were introduced in .NET 4.5 to make calling async methods easier and to make your async code more easily readable. The async/await API is syntactic sugar that uses the TPL (Task Parallel Library) behind the scenes. If you wanted to start a new task and have code run on the UI thread after the task completes prior .NET 4.5, your code would have looked something like this:

That’s not very pretty. Using async/await, the above becomes:

The above code gets compiled behind the scenes to the same TPL code as it does in the first example, so as noted, this is just syntactic sugar, and how sweet it is!

Using Async: Pitfalls

In reading about using async/await, you may have seen the phrase “async all the way” thrown around, but what does that really mean? Simply put, it means that any method that calls an async method (i.e. a method that has the async keyword in its signature) should use the await keyword when calling the async method. Not using the await keyword when calling an async method can result in exceptions that are thrown being swallowed by the runtime, which can cause issues that are difficult to track down. Using the await keyword requires that the calling method also use the async keyword in its signature. For example:

This poses a problem if you want to call an async method using the await keyword when you can’t use the async modifier on the calling method, for instance if the calling method is a method whose signature can’t use the async keyword or is a constructor or a method that the OS calls, such as GetView in an Android ArrayAdapter or GetCell in an iOS UITableViewDataSource. For example:

 

As you may know, an async method has to return either void, Task, or Task<T>, and returning void should only be used when making an event handler async. In the case of the GetView method noted above, you need to return an Android View, which can’t be changed to return Task<View> as the OS method that calls it obviously does not use the await keyword and so can’t handle a Task<T> being returned. Thus you can’t add the async keyword to the above method and therefore can’t use the await keyword when calling an async method from the above method.

To get around this, one might be tempted, as I have been in the past, to just call a method from GetView (or similar method where the signature can’t be changed regardless of the platform) as an intermediate method, and then call the async method from the intermediate method:

 

The problem here is that IntermediateMethod is now an async method and thus should be awaited just like the MyMethodAsync method needed to be. So, you have gained nothing here, as IntermediateMethod is now async and should be awaited. In addition, the GetView method will continue running all of the code after calling IntermediateMethod(), which may or may not be desirable. If the code following the call to IntermediateMethod() depends on the results of the IntermediateMethod(), then it isn’t desirable. In such a scenario, you may be tempted to use the Wait() method call (or Result property) on the async task, e.g.:

 

Calling Wait() on the async method causes the calling thread to pause until the async method completes. If this is the UI thread, as would be the case here, then your UI will hang while the async task runs. This isn’t good, especially in an ArrayAdapter that is supplying the data for the rows of a ListView. The user will not be able to interact with the list view until the data for all of the rows has been downloaded, and scrolling will likely be jerky and/or completely non-responsive, which isn’t a good user experience. There’s also a Result property you can call on the async task. This would be used if your async task was returning data by using Task<T> as the return type of the async method. This would also cause the calling thread to wait for the result of the async task:

 

In fact doing the above may cause your UI to hang completely and for the ListView never to be populated, which is a non-starter. It may also just be jerky:

JerkyListView

In general, you should avoid using Wait() and Result, especially on the UI thread. In the iOS and Android sample projects linked at the end of this blog, you can look in ViewControllerJerky and MainActivityJerky respectively to see this behavior. Those files are not set to compile in the sample projects.

Using Async All the Way

So how do I get “async all the way” in this scenario?

One way around the above problems is to revert to the old TPL upon which async/await is based. You’re going to use TPL directly, but only once to start the chain of async method calls (and to start a new thread right away). Somewhere down the line the TPL will be used directly again, as you need to use TPL to start a new thread. You can’t start a new thread using only the async/await keywords, so some method down the chain will have to launch the new thread with TPL (or another mechanism). The async method that launches a new thread will be a framework method, like a .NET HttpClient async method in many, if not most, cases. If not using async framework methods, then some method of yours down the chain will have to launch a new thread and return Task or Task<T>.

Let’s start with an example using GetView in an Android project (though the same concept will work for any platform, i.e. Xamarin.iOS, Xamarin.Forms, etc.) Let’s say I have a ListView that I want to populate with text downloaded from the web dynamically (more likely one would download the whole list of strings first and then populate the list rows with the already downloaded content, but I’m downloading the strings row by row here for demonstration purposes, plus there are occasions where one may want to do it this way anyway). I certainly don’t want to block the UI thread waiting for the multiple downloads; rather, I would like the user to be able to start working with the ListView, scroll around, and have the text appear in each ListView cell as the text gets downloaded. I also want to make sure that if a cell scrolls out of view, that when it is reused it will cancel loading the text that is in the process of being downloaded and start loading new text for that row instead. We do this with TPL and cancellation tokens. Comments in the code should explain what’s being done.

 

In a nutshell, the above method checks to see if this is a reused cell and, if so, we cancel the existing async text download if still incomplete. It then loads placeholder text into the cell, launches the async task to download the correct text for the row, and returns the view with placeholder text right away, thereby populating the ListView. This keeps the UI responsive and shows something in the cell while the launched task does its work of getting the correct text from the web. As the text gets downloaded, you’ll see the placeholders change to the downloaded text one-by-one (not necessarily in order due to differing download times). I added a random delay to the async task to simulate this behavior since I’m making such a simple, quick request.

Here’s the implementation of GetTextAsync(...):

 

Note that I can decorate the lambda passed into Task.Run() with the async keyword, thus allowing me to await the call to my async method, and thereby achieving “async all the way.” No more Jerky ListView!

SmoothListView

See it in action

If you want to see the above in action for Xamarin.iOS, Xamarin.Android, and Xamarin.Forms, check it out on my GitHub repo. The iOS version is very similar to the above, the only difference being in how I attach the CancellationTokenSource to the cell since there is no Tag property as there is in an Android View. Xamarin.Forms, however, does not have a direct equivalent to GetView or GetCell that I’m aware of, so I simulate the same behavior by launching an async task from the main App class constructor to get the text for each row.

Happy async coding!

 

원본 : https://blog.xamarin.com/getting-started-with-async-await/

심각도 코드 설명 프로젝트 파일 줄 비표시 오류(Suppression) 상태
오류  Your project is not referencing the "MonoAndroid,Version=v8.1" framework. Add a reference to "MonoAndroid,Version=v8.1" in the "frameworks" section of your project.json, and then re-run NuGet restore. DustInfo.Android   

빌드시 위와 같은 에러가 발생되었다.

구글 플레이 스토어에 앱을 올릴때도 오레오 버전에 타겟팅하라는 메세지가 나오던데

아마도 이와 관련이 있는듯 하다.

 

아래 처럼 프로젝트 속성에서

응용프로그램 탭에서 Android 버전을 사용하여 컴파일 부분을 Android 8.1 을 선택하고

Android 매니페스트 탭에서 대상 Android 버전Android 8.1 을 선택하면 해결된다.

참고

https://forums.xamarin.com/discussion/123705/error-mesage-your-project-is-not-referencing-the-monoandroid-version-v8-1

아래 내용은 DataGridView 의 row 를 마우스 드래그로 이동 시킬수 있는 코드입니다.

단, 직접 DataGridView 에 데이터를 작성해야 합니다. (아래 코드참고)

DataSource 에 데이터를 넣으면 에러가 발생됩니다.

            dataGridView.ColumnCount = 2;

            dataGridView.Columns[0].Name = "First";
            dataGridView.Columns[1].Name = "Last";
            dataGridView.Columns["First"].HeaderText = "First Name";
            dataGridView.Columns["Last"].HeaderText = "Last Name";
            dataGridView.Columns["First"].SortMode = DataGridViewColumnSortMode.Programmatic;
            dataGridView.Columns["Last"].SortMode = DataGridViewColumnSortMode.Programmatic;

            dataGridView.Rows.Add(new string[] { "공사명", "땡땡대학교 복도" });
            dataGridView.Rows.Add(new string[] { "공종", "토공" });
            dataGridView.Rows.Add(new string[] { "위치", "자재배송" });
            dataGridView.Rows.Add(new string[] { "내용", "노상다짐. 검측" });
            dataGridView.Rows.Add(new string[] { "일자", "2013.07" });

먼저 DataGridView 에 아래 처럼 이벤트를 먹이고 AllowDrop 을 True 합니다.

            this.dataGridView.MouseMove += dataGridView_MouseMove;
            this.dataGridView.MouseDown += dataGridView_MouseDown;
            this.dataGridView.DragOver += dataGridView_DragOver;
            this.dataGridView.DragDrop += dataGridView_DragDrop;
            this.dataGridView.AllowDrop = true;

그리고 아래 처럼 각 이벤트에 아래 처럼 코딩하면 row 를 이동시킬 수 있습니다.

        private Rectangle dragBoxFromMouseDown;
        private int rowIndexFromMouseDown;
        private int rowIndexOfItemUnderMouseToDrop;
        private void dataGridView_MouseMove(object sender, MouseEventArgs e)
        {
            if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
            {
                if (dragBoxFromMouseDown != Rectangle.Empty &&
                    !dragBoxFromMouseDown.Contains(e.X, e.Y))
                {

                    DragDropEffects dropEffect = dataGridView.DoDragDrop(dataGridView.Rows[rowIndexFromMouseDown], DragDropEffects.Move);
                }
            }
        }
        private void dataGridView_MouseDown(object sender, MouseEventArgs e)
        {
            rowIndexFromMouseDown = dataGridView.HitTest(e.X, e.Y).RowIndex;
            if (rowIndexFromMouseDown != -1)
            {
                Size dragSize = SystemInformation.DragSize;

                dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2), e.Y - (dragSize.Height / 2)), dragSize);
            }
            else
                 dragBoxFromMouseDown = Rectangle.Empty;
        }
        private void dataGridView_DragOver(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Move;
        }
        private void dataGridView_DragDrop(object sender, DragEventArgs e)
        {
 
            Point clientPoint = dataGridView.PointToClient(new Point(e.X, e.Y));

            rowIndexOfItemUnderMouseToDrop = dataGridView.HitTest(clientPoint.X, clientPoint.Y).RowIndex;

            if (e.Effect == DragDropEffects.Move)
            {
                DataGridViewRow rowToMove = e.Data.GetData(typeof(DataGridViewRow)) as DataGridViewRow;
                dataGridView.Rows.RemoveAt(rowIndexFromMouseDown);
                dataGridView.Rows.Insert(rowIndexOfItemUnderMouseToDrop, rowToMove);
            }
        }

1.       

        private Bitmap ConvertDataGridViewToBmp1(DataGridView dg)
        {
            int height = dg.Height;
            dg.Height = dg.RowCount * dg.RowTemplate.Height;

            Bitmap bitmap = new Bitmap(dg.Width, dg.Height);
            dg.DrawToBitmap(bitmap, new Rectangle(0, 0, dg.Width, dg.Height));

            dg.Height = height;

            return bitmap;
        }

 

2.

        [DllImport("gdi32.dll", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool BitBlt(IntPtr pHdc, int iX, int iY, int iWidth, int iHeight, IntPtr pHdcSource, int iXSource, int iYSource, System.Int32 dw);
        private const int src = 0xCC0020;

        private Bitmap ConvertDataGridViewToBmp2(DataGridView dg)
        {
            this.dataGridView.ColumnHeadersVisible = false;
            this.dataGridView.RowHeadersVisible = false;

            dg.Refresh();
            dg.Select();

            Graphics g = dg.CreateGraphics();
            Bitmap bitmap = new Bitmap(dg.ClientSize.Width, dg.ClientSize.Height, g);
            Graphics g = Graphics.FromImage(bitmap);
            IntPtr bitmapHoc = g.GetHdc();
            IntPtr gHoc = g.GetHdc();

            BitBlt(bitmapHoc, 0, 0, dg.ClientSize.Width, dg.ClientSize.Height, gHoc, 0, 0, src);

            g.ReleaseHdc(gHoc);

            g.ReleaseHdc(bitmapHoc);

            return bitmap;
        }

이미지 표현시 아래 처럼 에러가 발생되었다.

Failed to allocate a 88542732 byte allocation with 16768576 free bytes and 70MB until OOM

이미지 크기가 width 1440 , height 2560 을 넘으면 이런 에러가 발생된다고 한다.

이미지 크기를 조절하니 에러가 바로 사라졌다.

Xamarin Forms 에서

푸쉬알림을 Firebase, App Center 를 이용해서 처리하는 방법을 간략히 정리해봅니다.

1. Firebase 가입

https://firebase.google.com/ 가입 후 (구글 및 다른 계정으로도 로그인 가능)

https://console.firebase.google.com/ 로 이동하여 프로젝트 추가

Android 앱에 Firebase 추가 선택

안드로이드 프로젝트의 패키지명 기입 후 앱등록 이후 2,3 단계는 그냥 확인.

좌측 상단의 톱니바퀴 선택 후 프로젝트 설정으로 이동하고

클라우드 메시징 탭을 선택.

위그림과 같이 Server Key 와 SenderId 정보를 기억.

 

2. Xamarin Forms 프로젝트 구성 (.Net Standard)

 

 

3. Nuget 에서 Microsoft.AppCenter.Push 설치

 

4. App Center 가입

https://appcenter.ms 사이트로 이동하여 가입 (마이크로소프트 계정 및 구글, 페이스북 으로 로그인 가능)

App 만들기 하여 아래 그림과 같이 Android 와 Xamarin 을 선택 하여 이름 지정 후 생성

Push 를 선택하고 가이드에 따라 코딩.


AndroidManifest.xml 파일에 아래 내용  추가
<permission android:protectionLevel="signature"android:name="${applicationId}.permission.C2D_MESSAGE" />
<uses-permissionandroid:name="${applicationId}.permission.C2D_MESSAGE" />

${applicationId} 은 패키지명으로 변경 해야함.


안드로이드인 경우 아래 처럼
Push.SetSenderId("{SenderId}");
AppCenter.Start("282b7f5d-18b4-4e26-8920-8414d6df405b", typeof(Push));

Xamarin Forms 인 경우 아래 처럼 코딩
Push.SetSenderId("{SenderId}");
LoadApplication(new App());

SenderId 는 1번에서 기억해 놓은 senderID 를 이용

▼ Firebase 의 Server Key 기입

 

5. 추가 프로젝트 설정

안드로이드에서 permission 을 INTERNET 도 주어야 함

AndroidManifest.xml 파일에 아래 내용  추가

<uses-permission android:name="android.permission.INTERNET" />

 

 

참고링크

https://docs.microsoft.com/en-us/appcenter/sdk/push/xamarin-android

 

다른 방법

https://onesignal.com 을 통해서도 처리 가능

=> https://www.youtube.com/watch?v=EPIrNxuwAj8&t=851s
=> https://documentation.onesignal.com/docs/xamarin-sdk-setup

+ Recent posts

티스토리 툴바