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

https://www.youtube.com/watch?v=eWrL5VQnVr8&feature=youtu.be

https://github.com/nguyenthanhliemfc/GuessNumberGame

 

 

이미지 URL 주소를 가지고 화면에 표시하고자 할 때 사용한다. 

       private Bitmap GetImageBitmapFromUrl(string url)
        {
            Bitmap imageBitmap = null;

            using (var webClient = new WebClient())
            {
                var imageBytes = webClient.DownloadData(url);
                if (imageBytes != null && imageBytes.Length > 0)
                {
                    imageBitmap = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length);
                }
            }

            return imageBitmap;
        }

 

사용은 아래와 같다.

imageView.SetImageBitmap(GetImageBitmapFromUrl(urlString));

 

추가로 아래과 같은 방법이 있는데

제대로 동작하지 않는다.;

                    // 2. FAIL
                    //URL url = new URL(urlString);
                    //Bitmap bitmap = BitmapFactory.DecodeStream(url.OpenStream());
                    //imageView.SetImageBitmap(bitmap);

                    // 3. FAIL
                    //imageView.SetImageURI(Android.Net.Uri.Parse(urlString));

 

 

                    WebView localWebView = FindViewById<WebView>(Resource.Id.LocalWebView);
                    localWebView.SetWebViewClient(new WebViewClient());

                    string html = $@"
<html>
 <body bgcolor='black'>
  <a href ='{urlString}' target='_blank'>
   <div style='width: 280px; height: 230px; overflow: hidden; position: relative;'>
    <img src='{urlString}' style='position: absolute; top:-15px; left:-95px; width:430px; height: 240px;'/>
   </div>
  </a>
 </body>
</html>
";

                    localWebView.LoadData(html, "text/html", null);

 

 

이미지 중심을 기준으로 해당 크기로 자른다.

 

        public static Bitmap CropCenterBitmap(Bitmap src, int w, int h)
        {
            if (src == null)
                return null;

            int width = src.Width;
            int height = src.Height;

            if (width < w && height < h)
                return src;

            int x = 0;
            int y = 0;

            if (width > w)
                x = (width - w)/ 2;

            if (height > h)
                y = (height - h)/ 2;

            int cw = w; // crop width
            int ch = h; // crop height

            if (w > width)
                cw = width;

            if (h > height)
                ch = height;

            return Bitmap.CreateBitmap(src, x, y, cw, ch);
        }

Checking Battery Status

Use DependencyService to access battery information natively for each platform

PDF for offline use
Sample Code:
Related Samples:

last updated: August 2016

This article walks through the creation of an application that checks battery status. This article is based on the Battery Plugin by James Montemagno. For more information, see the GitHub repo.

Because Xamarin.Forms does not include functionality for checking the current battery status, this application will need to use DependencyService to take advantage of native APIs. This article will cover the following steps for using DependencyService:

When completed, the application using DependencyService will have the following structure:

Creating the Interface

First, create an interface in shared code that expresses the desired functionality. In the case of a battery checking application, the relevant information is the percentage of the battery remaining, whether the device is charging or not, and how the device is receiving power:

namespace DependencyServiceSample
{
  public enum BatteryStatus
  {
    Charging,
    Discharging,
    Full,
    NotCharging,
    Unknown
  }

  public enum PowerSource
  {
    Battery,
    Ac,
    Usb,
    Wireless,
    Other
  }

  public interface IBattery
  {
    int RemainingChargePercent { get; }
    BatteryStatus Status { get; }
    PowerSource PowerSource { get; }
  }
}

Coding against this interface in the shared code will allow the Xamarin.Forms app to access the power management APIs on each platform.

ℹ️

Note: Classes implementing the Interface must have a parameterless constructor to work with the DependencyService. Constructors can't be defined by interfaces.

iOS Implementation

The IBattery interface must be implemented in each platform-specific application project. The iOS implementation will use the native UIDevice APIs to access battery information. Note that the following class has a parameterless constructor so that the DependencyService can create new instances:

using UIKit;
using Foundation;
using DependencyServiceSample.iOS;

namespace DependencyServiceSample.iOS
{
  public class BatteryImplementation : IBattery
  {
    public BatteryImplementation()
    {
      UIDevice.CurrentDevice.BatteryMonitoringEnabled = true;
    }

    public int RemainingChargePercent
    {
      get
      {
        return (int)(UIDevice.CurrentDevice.BatteryLevel * 100F);
      }
    }

    public BatteryStatus Status
    {
      get
      {
        switch (UIDevice.CurrentDevice.BatteryState)
        {
          case UIDeviceBatteryState.Charging:
            return BatteryStatus.Charging;
          case UIDeviceBatteryState.Full:
            return BatteryStatus.Full;
          case UIDeviceBatteryState.Unplugged:
            return BatteryStatus.Discharging;
          default:
            return BatteryStatus.Unknown;
        }
      }
    }

    public PowerSource PowerSource
    {
      get
      {
        switch (UIDevice.CurrentDevice.BatteryState)
        {
          case UIDeviceBatteryState.Charging:
            return PowerSource.Ac;
          case UIDeviceBatteryState.Full:
            return PowerSource.Ac;
          case UIDeviceBatteryState.Unplugged:
            return PowerSource.Battery;
          default:
            return PowerSource.Other;
        }
      }
    }
  }
}

Finally, add this [assembly] attribute above the class (and outside any namespaces that have been defined), including any required using statements:

using UIKit;
using Foundation;
using DependencyServiceSample.iOS;//necessary for registration outside of namespace

[assembly: Xamarin.Forms.Dependency (typeof (BatteryImplementation))]
namespace DependencyServiceSample.iOS
{
  public class BatteryImplementation : IBattery {
    ...

This attribute registers the class as an implementation of the IBattery interface, which means that DependencyService.Get<IBattery> can be used in shared code to create an instance of it:

Android Implementation

The Android implementation uses the Android.OS.BatteryManager API. This implementation is more complex than the iOS version, requiring checks to handle lack of battery permissions:

using System;
using Android;
using Android.Content;
using Android.App;
using Android.OS;
using BatteryStatus = Android.OS.BatteryStatus;
using DependencyServiceSample.Droid;

namespace DependencyServiceSample.Droid
{
  public class BatteryImplementation : IBattery
  {
    private BatteryBroadcastReceiver batteryReceiver;
    public BatteryImplementation() { }

    public int RemainingChargePercent
    {
      get
      {
        try
        {
          using (var filter = new IntentFilter(Intent.ActionBatteryChanged))
          {
            using (var battery = Application.Context.RegisterReceiver(null, filter))
            {
              var level = battery.GetIntExtra(BatteryManager.ExtraLevel, -1);
              var scale = battery.GetIntExtra(BatteryManager.ExtraScale, -1);

              return (int)Math.Floor(level * 100D / scale);
            }
          }
        }
        catch
        {
          System.Diagnostics.Debug.WriteLine ("Ensure you have android.permission.BATTERY_STATS");
          throw;
        }

      }
    }

    public DependencyServiceSample.BatteryStatus Status
    {
      get
      {
        try
        {
          using (var filter = new IntentFilter(Intent.ActionBatteryChanged))
          {
            using (var battery = Application.Context.RegisterReceiver(null, filter))
            {
              int status = battery.GetIntExtra(BatteryManager.ExtraStatus, -1);
              var isCharging = status == (int)BatteryStatus.Charging || status == (int)BatteryStatus.Full;

              var chargePlug = battery.GetIntExtra(BatteryManager.ExtraPlugged, -1);
              var usbCharge = chargePlug == (int)BatteryPlugged.Usb;
              var acCharge = chargePlug == (int)BatteryPlugged.Ac;
              bool wirelessCharge = false;
              wirelessCharge = chargePlug == (int)BatteryPlugged.Wireless;

              isCharging = (usbCharge || acCharge || wirelessCharge);
              if (isCharging)
                return DependencyServiceSample.BatteryStatus.Charging;

              switch(status)
              {
                case (int)BatteryStatus.Charging:
                  return DependencyServiceSample.BatteryStatus.Charging;
                case (int)BatteryStatus.Discharging:
                  return DependencyServiceSample.BatteryStatus.Discharging;
                case (int)BatteryStatus.Full:
                  return DependencyServiceSample.BatteryStatus.Full;
                case (int)BatteryStatus.NotCharging:
                  return DependencyServiceSample.BatteryStatus.NotCharging;
                default:
                  return DependencyServiceSample.BatteryStatus.Unknown;
              }
            }
          }
        }
        catch
        {
          System.Diagnostics.Debug.WriteLine ("Ensure you have android.permission.BATTERY_STATS");
          throw;
        }
      }
    }

    public PowerSource PowerSource
    {
      get
      {
        try
        {
          using (var filter = new IntentFilter(Intent.ActionBatteryChanged))
          {
            using (var battery = Application.Context.RegisterReceiver(null, filter))
            {
              int status = battery.GetIntExtra(BatteryManager.ExtraStatus, -1);
              var isCharging = status == (int)BatteryStatus.Charging || status == (int)BatteryStatus.Full;

              var chargePlug = battery.GetIntExtra(BatteryManager.ExtraPlugged, -1);
              var usbCharge = chargePlug == (int)BatteryPlugged.Usb;
              var acCharge = chargePlug == (int)BatteryPlugged.Ac;

              bool wirelessCharge = false;
              wirelessCharge = chargePlug == (int)BatteryPlugged.Wireless;

              isCharging = (usbCharge || acCharge || wirelessCharge);

              if (!isCharging)
                return DependencyServiceSample.PowerSource.Battery;
              else if (usbCharge)
                return DependencyServiceSample.PowerSource.Usb;
              else if (acCharge)
                return DependencyServiceSample.PowerSource.Ac;
              else if (wirelessCharge)
                return DependencyServiceSample.PowerSource.Wireless;
              else
                return DependencyServiceSample.PowerSource.Other;
            }
          }
        }
        catch
        {
          System.Diagnostics.Debug.WriteLine ("Ensure you have android.permission.BATTERY_STATS");
          throw;
        }
      }
    }
  }
}

Add this [assembly] attribute above the class (and outside any namespaces that have been defined), including any required using statements:

...
using BatteryStatus = Android.OS.BatteryStatus;
using DependencyServiceSample.Droid; //enables registration outside of namespace

[assembly: Xamarin.Forms.Dependency (typeof (BatteryImplementation))]
namespace DependencyServiceSample.Droid
{
  public class BatteryImplementation : IBattery {
    ...

This attribute registers the class as an implementation of the IBattery interface, which means that DependencyService.Get<IBattery> can be used in the shared code can create an instance of it.

Windows Phone Implementation

This implementation is more limited than the Android and iOS versions because the Windows Phone power API provides less information than the Android and iOS equivalents.

using System;
using Windows.ApplicationModel.Core;
using DependencyServiceSample.WinPhone;

namespace DependencyServiceSample.WinPhone
{
  public class BatteryImplementation : IBattery
  {
    private int last;
    private BatteryStatus status = BatteryStatus.Unknown;

    public BatteryImplementation()
    {
      last = DefaultBattery.RemainingChargePercent;
    }

    Windows.Phone.Devices.Power.Battery battery;
    private Windows.Phone.Devices.Power.Battery DefaultBattery
    {
      get { return battery ?? (battery = Windows.Phone.Devices.Power.Battery.GetDefault()); }
    }
    public int RemainingChargePercent
    {
      get
      { return DefaultBattery.RemainingChargePercent; }
    }

    public  BatteryStatus Status
    {
      get { return status; }
    }

    public PowerSource PowerSource
    {
      get
      {
        if (status == BatteryStatus.Full || status == BatteryStatus.Charging)
          return PowerSource.Ac;

        return PowerSource.Battery;
      }
    }
  }
}

Add this [assembly] attribute above the class (and outside any namespaces that have been defined), including any required using statements.

using System;
using Windows.ApplicationModel.Core;
using DependencyServiceSample.WinPhone;

[assembly: Xamarin.Forms.Dependency (typeof (BatteryImplementation))]
namespace DependencyServiceSample.WinPhone {
  public class BatteryImplementation : IBattery {
    ...

This attribute registers the class as an implementation of the IBattery interface, which means that DependencyService.Get<IBattery> can be used in shared code to create an instance of it.

Universal Windows Platform Implementation

The UWP implementation uses the Windows.Devices.Power APIs to obtain battery status information:

using DependencyServiceSample.UWP;
using Xamarin.Forms;

[assembly: Dependency(typeof(BatteryImplementation))]
namespace DependencyServiceSample.UWP
{
    public class BatteryImplementation : IBattery
    {
        private BatteryStatus status = BatteryStatus.Unknown;
        Windows.Devices.Power.Battery battery;

        public BatteryImplementation()
        {
        }

        private Windows.Devices.Power.Battery DefaultBattery
        {
            get
            {
                return battery ?? (battery = Windows.Devices.Power.Battery.AggregateBattery);
            }
        }

        public int RemainingChargePercent
        {
            get
            {
                var finalReport = DefaultBattery.GetReport();
                var finalPercent = -1;

                if (finalReport.RemainingCapacityInMilliwattHours.HasValue && finalReport.FullChargeCapacityInMilliwattHours.HasValue)
                {
                    finalPercent = (int)((finalReport.RemainingCapacityInMilliwattHours.Value /
                        (double)finalReport.FullChargeCapacityInMilliwattHours.Value) * 100);
                }
                return finalPercent;
            }
        }

        public BatteryStatus Status
        {
            get
            {
                var report = DefaultBattery.GetReport();
                var percentage = RemainingChargePercent;

                if (percentage >= 1.0)
                {
                    status = BatteryStatus.Full;
                }
                else if (percentage < 0)
                {
                    status = BatteryStatus.Unknown;
                }
                else
                {
                    switch (report.Status)
                    {
                        case Windows.System.Power.BatteryStatus.Charging:
                            status = BatteryStatus.Charging;
                            break;
                        case Windows.System.Power.BatteryStatus.Discharging:
                            status = BatteryStatus.Discharging;
                            break;
                        case Windows.System.Power.BatteryStatus.Idle:
                            status = BatteryStatus.NotCharging;
                            break;
                        case Windows.System.Power.BatteryStatus.NotPresent:
                            status = BatteryStatus.Unknown;
                            break;
                    }
                }
                return status;
            }
        }

        public PowerSource PowerSource
        {
            get
            {
                if (status == BatteryStatus.Full || status == BatteryStatus.Charging)
                {
                    return PowerSource.Ac;
                }
                return PowerSource.Battery;
            }
        }
    }
}

The [assembly] attribute above the namespace declaration registers the class as an implementation of the IBattery interface, which means that DependencyService.Get<IBattery> can be used in shared code to create an instance of it.

Implementing in Shared Code

Now that the interface has been implemented for each platform, the shared application can be written to take advantage of it. The application will consist of a page with a button that when tapped updates its text with the current battery status. It uses the DependencyService to get an instance of the IBattery interface. At runtime, this instance will be the platform-specific implementation that has full access to the native SDK.

public MainPage ()
{
    var button = new Button {
        Text = "Click for battery info",
        VerticalOptions = LayoutOptions.CenterAndExpand,
        HorizontalOptions = LayoutOptions.CenterAndExpand,
    };
    button.Clicked += (sender, e) => {
        var bat = DependencyService.Get<IBattery>();

        switch (bat.PowerSource){
          case PowerSource.Battery:
            button.Text = "Battery - ";
            break;
          case PowerSource.Ac:
            button.Text = "AC - ";
            break;
          case PowerSource.Usb:
            button.Text = "USB - ";
            break;
          case PowerSource.Wireless:
            button.Text = "Wireless - ";
            break;
          case PowerSource.Other:
          default:
            button.Text = "Other - ";
            break;
        }
        switch (bat.Status){
          case BatteryStatus.Charging:
            button.Text += "Charging";
            break;
          case BatteryStatus.Discharging:
            button.Text += "Discharging";
            break;
          case BatteryStatus.NotCharging:
            button.Text += "Not Charging";
            break;
          case BatteryStatus.Full:
            button.Text += "Full";
            break;
          case BatteryStatus.Unknown:
          default:
            button.Text += "Unknown";
            break;
        }
    };
    Content = button;
}

Running this application on iOS, Android, or the Windows platforms and pressing the button will result in the button text updating to reflect the current power status of the device.

http://www.c-sharpcorner.com/article/building-a-simple-working-memory-game-app-with-web-api-and-signalr/

 

심각도 코드 설명 프로젝트 파일 줄 비표시 오류(Suppression) 상태
오류  C:\Users\kjun\.nuget\packages\xamarin.forms\2.5.0.122203\build\netstandard1.0\Xamarin.Forms.Build.Tasks.dll 어셈블리에서 "Xamarin.Forms.Build.Tasks.GetTasksAbi" 작업을 로드할 수 없습니다.  <UsingTask> 선언이 올바른지, 어셈블리와 여기에 종속되어 있는 어셈블리를 모두 사용할 수 있는지, 작업에 Microsoft.Build.Framework.ITask를 구현하는 공용 클래스가 포함되어 있는지 확인하십시오. CaneraSketching.Android   

새로 만든 Xamarin Form 프로젝트가 위와 같은 에러가 발생되었다.;;

아 이건 또 먼가 하고 찾아보다가 혹시나해서 이전에 만든 Xamarin Form 프로젝트를 빌드하니 역시나 똑같은 에러가 발생된다;;

찾아보니 xamarin from 업그레이드 이후 발생되는 에러라고 하는데 (링크참고)

https://forums.xamarin.com/discussion/106784/error-with-latest-nuget-v2-5-0-77-xamarin-forms-build-tasks-gettasksabi-task-could-not-be-loaded

처음엔 프로젝트를 정리하고 다시 빌드하니 오류가 사라졌다.

핸드폰까지 디버깅이 제대로 되는걸 확인 후 수정후 다시 배포하려는데

또 같은 에러가 발생되었다.;;

이번에는 정리해도 안된다;;;

그래서 Visual Studio 를 껐다가 다시켜니 된다.;;

즉, 정리해보고 안되면 Visual Studio 를 껐다켜야한다.

매번 이작업을 해야한다.;;

아;; 위 링크데로 이번 최신버전(2.5.0)의 문제인 것 같다 ... ㅜㅠ

Android 에서 Service 를 만드는 방법입니다.

Service 는 어플리케이션 동작에 상관없이 무언가를 수행하고자 할때 사용됩니다.

 

1. 서비스 만들기

KService 클래스 파일을 하나만듭니다. (이름은 아무거나)

아래 처럼 해당 서비스에는 Service (Android.App.Service) 를 상속 받도록합니다.

Exported 속성은 false 로 하게 되면 실행되는 어플리케이션에 종속되게되어

어플리케이션이 닫히면 서비스도 중단됩니다.

Exported 속성을 true 로 하게 되면 어플리케이션과는 무관하게 서비스가 독립적으로 구동됩니다.

당연히 어플리케이션이 닫혀도 계속 동작하게 됩니다.

Name 은 서비스의 고유 이름입니다. 전역서비스인 경우 이 이름으로 접근하여 핸들링할 수 있습니다.

    [Service(Exported = true, Name = "kr.kjun.KService")]
    public class KService : Service
    {

        /// <summary>
        /// 서비스 객체와 화면간의 데이터를 주고 받고자 할 때 사용되는 메서드로
        /// 데이터를 전달할 필요가 없으면 return null 로 둡니다.
        /// </summary>
        /// <param name="intent"></param>
        /// <returns></returns>
        public override IBinder OnBind(Intent intent)
        {
            return null;
        }

        public override StartCommandResult OnStartCommand(Android.Content.Intent intent, StartCommandFlags flags, int startId)
        {

            // 여기에 수행할 액션을 처리합니다.

             return StartCommandResult.Sticky;
        }

        /// <summary>
        /// 서비스에서 가장 먼저 호출됩니다.(최초에 한번만)
        /// </summary>
        public override void OnCreate()
        {
            base.OnCreate();
        }

        /// <summary>
        /// 서비스가 종료될 때 실행됩니다.
        /// </summary>
        public override void OnDestroy()
        {
            base.OnDestroy();
        }

    }

실제 서비스에서 처리할 로직의 코드가 들어갈 부분은 OnStartCommand 메서드 부분입니다.

return 의 종류가 총 5개가 있는데 가장많이 사용되는 것은 세자기로

Sticky
Service가 강제 종료되었을 경우 시스템이 다시 Service를 재시작 시켜 주지만 intent 값을 null로 초기화 시켜서 재시작 합니다. 
Service 실행시 StartService(Intent service) 메서드를 호출 하는데 OnStartCommand(Intent intent, int flags, int startId) 메서드에 intent로 value를 넘겨 줄 수 있습니다.
기존에 intent에 value값이 설정이 되있다고 하더라도 Service 재시작시 intent 값이 null로 초기화 되서 재시작 됩니다.

NotSticky
이 Flag를 리턴해 주시면, 강제로 종료 된 Service가 재시작 하지 않습니다. 시스템에 의해 강제 종료되어도 괸찮은 작업을 진행 할 때 사용해 주시면 됩니다.

RedeliverIntent
Service가 종료 되었을 경우 시스템이 다시 Service를 재시작 시켜 주지만 intent 값을 그대로 유지 시켜 줍니다. StartService() 메서드 호출시 Intent value값을 사용한 경우라면 해당 Flag를 사용해서 리턴값을 설정해 주면 됩니다.

참고 : https://developer.xamarin.com/api/type/Android.App.StartCommandResult/

저같은 경우는 타이머를 동작 시켜 특정 작업을 주기적으로 DB 에 담는 처리를 하였습니다.

 

2. 서비스 등록하기

서비스를 아무리 잘만들었어도 등록되지 않으면 구동되지 않고 에러가 납니다.

아래 처럼 AndroidManifest.xml 파일에 서비스를 등록해 주어야합니다.

Service 이름은 위에서 지정한 Name 이름을 넣습니다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="11" android:versionName="2.0" package="kr.kjun.pushcoin" android:installLocation="auto">
 <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="23" />
  ........
  ........
 <application android:allowBackup="true" android:label="@string/app_name" android:icon="@drawable/icon">
  <service android:name="kr.kjun.KService" android:exported="true"></service>
  ........
  ........
 </application>
</manifest>

 

3. 서비스 구동하기

이제 서비스 구동 준비는 되었고 원하는 시기에 서비스가 동작하도록 코딩을 해야합니다.

옐호 어플리케이션 시작시에 동작시킨다면

MainActivity.cs 에서 OnCreate 메서드에 아래 처럼 코딩하면 서비스가 시작됩니다.

KService kService = new Intent(this, typeof(KService));

StartService(kService);

 

4. 서비스 구동여부 확인하는 방법

아래 코드는 해당 서비스가 동작하고 있는지 여부를 리턴해 줍니다.

이를 확인하여 서비스 중복 실행을 방지합니다.

위에서 정의한 Name 항목으로 서비스를 찾을수 있습니다.

        /// <summary>
        /// 현재 서비스가 실행중인지 확인합니다.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="serviceName">찾을 서비스 명입니다.</param>
        /// <returns></returns>
        public static bool IsServiceRunningCheck(Context context, string serviceName)
        {
            ActivityManager manager = (ActivityManager)context.GetSystemService(Activity.ActivityService);

            ActivityManager.RunningServiceInfo service 
                                        = manager.GetRunningServices(int.MaxValue).Where(c => c.Service.ClassName.Equals(serviceName)).FirstOrDefault();

            if(service != null) return true;

            return false;
        }

missing adactivity with android.configchanges in androidmanifest.xml

광고를 붙일때 위와같은 에러가 광고창에 찍혔다.

확인해 보니 AndroidManifest.xml 파일에 코드를 추가해 주어야한다.

전체구조는 아래 와 같다 굵은색이 추가한 부분이고 기본적으로 permission 도 아래처럼 주어야한다.

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="dustSeocheon.dustSeocheon" android:installLocation="auto">
 <uses-sdk android:minSdkVersion="21" />
 <uses-permission android:name="android.permission.INTERNET" />
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 <application android:allowBackup="true" android:label="@string/app_name">
    <!-- Google Mobile Ads Activity -->
    <activity android:name="com.google.android.gms.ads.AdActivity"
              android:label="@string/app_name"
              android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">
    </activity>
    <!-- Denote the referenced Google Play services version -->
    <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />

  </application>
</manifest>

+ Recent posts

티스토리 툴바