2017년 7월 13일 목요일

Visual Studio 에서 Sublime Text나 Visual Studio Code의 멀티 셀렉트 기능을 하려면?

Sublime Text에서 Mac의 경우 CMD + D 윈도우의 경우 Ctrl + D 기능을 아주 좋아 한다.

코드를 작성 하다가 변수를 쫙 선택 해서 이름을 변경 한다 든지 아주 유용한 기능이다.

Sublime Text 사이트에서 동영상을 보고 반하지 않을수 없는 기능이었다.

Visual Studio Code를 가끔 사용하는데 왠지 Sublime Text와 비슷한 느낌이고 역시
기능이나 단축키가 비슷하고 좋다.

Visual Studio Code 역시 같은 기능이 존재 한다.

그러나 Visual Studio는 그 기능이 없다.

요즘 윈도우 어플리케이션 개발을 많이 하기에 Visual Studio도 많이 사용한다.

Visual Studio에서도 멀티 셀렉트 기능을 사용하고 싶어져서 검색을 해보 았다.

역쉬 있더라..

https://marketplace.visualstudio.com/items?itemName=MarcoAlamia-CodingLabs.MixEdit

위 링크에 플러그인을 설치 해줘야 동일 한 기능을 맛볼 수 있다.

이 플러그인 역시 Sublime Text 처럼 동작 동영상이 있다.



2017년 3월 8일 수요일

Xcode 8.2.1 application building시 크래쉬 발생

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Application Specific Information:
ProductBuildVersion: 8C1002
UNCAUGHT EXCEPTION (NSRangeException): *** -[__NSArrayM objectAtIndex:]: index 3 beyond bounds [0 .. 2]
UserInfo: (null)
Hints: 
  0: Creation Backtrace for Notification Token:

  0   -[_DVTNotificationReceiver initWithBlock:queue:] (in DVTFoundation)
  1   -[NSNotificationCenter(DVTNSNotificationCenterAdditions) dvt_addObserverForName:object:queue:usingBlock:] (in DVTFoundation)
  2   -[_IDENavigatorOutlineViewDataSource setRootItems:] (in IDEKit)
  3   -[IDENavigatorOutlineView _updateRootItems:sortDescriptors:] (in IDEKit)
  4   -[IDENavigatorOutlineView setRootItems:] (in IDEKit)
  5   -[IDENavigatorOutlineView _updateBoundContentArrayOrSet] (in IDEKit)
  6   -[IDENavigatorOutlineView updateBoundContentArray] (in IDEKit)
  7   -[NSObject(DVTBindingUtilities) updateBoundValueForBinding:] (in DVTKit)
  8   -[DVTBindingHelper observeValueForKeyPath:ofObject:change:context:] (in DVTKit)
  9   NSKeyValueNotifyObserver (in Foundation)
 10   NSKeyValueDidChange (in Foundation)
 11   -[NSObject(NSKeyValueObservingPrivate) _changeValueForKey:key:key:usingBlock:] (in Foundation)
 12   _NSSetObjectValueAndNotify (in Foundation)
 13   -[IDEBatchFindNavigator updateScopeItems:] (in IDEKit)
 14   __44-[IDEBatchFindNavigator setupLocationPicker]_block_invoke_2 (in IDEKit)
 15   -[NSObject(DVTObservingConvenience) _dvt_newObserverForKeyPath:options:owner:creationBacktrace:withHandlerBlock:] (in DVTFoundation)
 16   -[NSObject(DVTObservingConvenience) dvt_newObserverForKeyPath:options:withHandlerBlock:] (in DVTFoundation)
 17   -[IDEBatchFindNavigator setupLocationPicker] (in IDEKit)
 18   -[IDEBatchFindNavigator viewDidInstall] (in IDEKit)
 19   -[DVTViewController _viewDidInstall] (in DVTKit)
 20   -[_DVTViewController_ViewLifecycleInterpositions viewDidMoveToWindow] (in DVTKit)
 21   -[NSView _setWindow:] (in AppKit)
 22   -[NSView addSubview:] (in AppKit)
 23   __42-[DVTReplacementView _setupViewController]_block_invoke (in DVTKit)
 24   DVTInvokeWithFailureHint (in DVTFoundation)
 25   -[DVTReplacementView _setupViewController] (in DVTKit)
 26   -[DVTReplacementView installedViewController] (in DVTKit)
 27   -[DVTReplacementView layoutTopDown] (in DVTKit)
 28   -[DVTLayoutView_ML _reallyLayoutIfNeededTopDown] (in DVTKit)
 29   +[DVTLayoutView_ML _doRecursivelyLayoutSubviewsOfView:populatingSetWithLaidOutViews:completionCallBackHandlers:currentLayoutPass:needsSecondPass:] (in DVTKit)
 30   +[DVTLayoutView_ML _doRecursivelyLayoutSubviewsOfView:populatingSetWithLaidOutViews:completionCallBackHandlers:currentLayoutPass:needsSecondPass:] (in DVTKit)
 31   +[DVTLayoutView_ML _doRecursivelyLayoutSubviewsOfView:populatingSetWithLaidOutViews:completionCallBackHandlers:currentLayoutPass:needsSecondPass:] (in DVTKit)
 32   +[DVTLayoutView_ML _doRecursivelyLayoutSubviewsOfView:populatingSetWithLaidOutViews:completionCallBackHandlers:currentLayoutPass:needsSecondPass:] (in DVTKit)
 33   +[DVTLayoutView_ML _doRecursivelyLayoutSubviewsOfView:populatingSetWithLaidOutViews:completionCallBackHandlers:currentLayoutPass:needsSecondPass:] (in DVTKit)
 34   +[DVTLayoutView_ML _doRecursivelyLayoutSubviewsOfView:populatingSetWithLaidOutViews:completionCallBackHandlers:currentLayoutPass:needsSecondPass:] (in DVTKit)
 35   +[DVTLayoutView_ML _recursivelyLayoutSubviewsOfView:populatingSetWithLaidOutViews:] (in DVTKit)
 36   -[DVTLayoutView_ML viewWillDraw] (in DVTKit)
 37   -[NSView viewWillDraw] (in AppKit)
 38   -[NSView viewWillDraw] (in AppKit)
 39   -[NSView viewWillDraw] (in AppKit)
 40   -[NSView _sendViewWillDrawInRect:clipRootView:] (in AppKit)
 41   -[NSView displayIfNeeded] (in AppKit)
 42   -[NSWindow displayIfNeeded] (in AppKit)
 43   ___NSWindowGetDisplayCycleObserver_block_invoke6365 (in AppKit)
 44   __37+[NSDisplayCycle currentDisplayCycle]_block_invoke (in AppKit)
 45   CA::Transaction::run_commit_handlers(CATransactionPhase) (in QuartzCore)
 46   CA::Context::commit_transaction(CA::Transaction*) (in QuartzCore)
 47   CA::Transaction::commit() (in QuartzCore)
 48   CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) (in QuartzCore)
 49   __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ (in CoreFoundation)
 50   __CFRunLoopDoObservers (in CoreFoundation)
 51   CFRunLoopRunSpecific (in CoreFoundation)
 52   RunCurrentEventLoopInMode (in HIToolbox)
 53   ReceiveNextEventCommon (in HIToolbox)
 54   _BlockUntilNextEventMatchingListInModeWithFilter (in HIToolbox)
 55   _DPSNextEvent (in AppKit)
 56   -[NSApplication _nextEventMatchingEventMask:untilDate:inMode:dequeue:] (in AppKit)
 57   -[DVTApplication nextEventMatchingMask:untilDate:inMode:dequeue:] (in DVTKit)
 58   -[NSApplication run] (in AppKit)
 59   NSApplicationMain (in AppKit)
 60   start (in libdyld.dylib)

Backtrace:
  0   __exceptionPreprocess (in CoreFoundation)
  1   DVTFailureHintExceptionPreprocessor (in DVTFoundation)
  2   objc_exception_throw (in libobjc.A.dylib)
  3   -[__NSArrayM objectAtIndex:] (in CoreFoundation)
  4   -[_IDENavigatorOutlineViewDataSource outlineView:child:ofItem:] (in IDEKit)
  5   refreshRowEntryItemAndLevelInfo (in AppKit)
  6   -[NSOutlineView reloadItem:reloadChildren:] (in AppKit)
  7   -[IDENavigatorOutlineView reloadItem:reloadChildren:] (in IDEKit)
  8   __83-[_IDENavigatorOutlineViewDataSource _processNavigableItemGraphChangeNotification:]_block_invoke.735 (in IDEKit)
  9   +[NSAnimationContext(DVTNSAnimationContextAdditions) dvt_nonAnimatedBlock:] (in DVTKit)
 10   -[IDENavigatorOutlineView suspendEditingWhilePerformingBlock:] (in IDEKit)
 11   -[_IDENavigatorOutlineViewDataSource _processNavigableItemGraphChangeNotification:] (in IDEKit)
 12   DVTInvokeWithLazyFailureHint (in DVTFoundation)
 13   __48-[_DVTNotificationReceiver receiveNotification:]_block_invoke.42 (in DVTFoundation)
 14   -[_DVTNotificationReceiver receiveNotification:] (in DVTFoundation)
 15   __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ (in CoreFoundation)
 16   ___CFXRegistrationPost_block_invoke (in CoreFoundation)
 17   _CFXRegistrationPost (in CoreFoundation)
 18   ___CFXNotificationPost_block_invoke (in CoreFoundation)
 19   -[_CFXNotificationRegistrar find:object:observer:enumerator:] (in CoreFoundation)
 20   _CFXNotificationPost (in CoreFoundation)
 21   -[NSNotificationCenter postNotificationName:object:userInfo:] (in Foundation)
 22   -[NSNotificationCenter(DVTNSNotificationCenterAdditions) _dvt_postNotificationName:object:userInfo:] (in DVTFoundation)
 23   -[IDENavigableItemCoordinator _postNotificationNamed:forChangedItems:] (in IDEKit)
 24   -[IDENavigableItemCoordinator _delayedPostGraphAndPropertyChangeNotifications] (in IDEKit)
 25   __48-[DVTDelayedInvocation initWithTarget:selector:]_block_invoke (in DVTFoundation)
 26   -[DVTDelayedInvocation runBlock:] (in DVTFoundation)
 27   __NSFirePerformWithOrder (in Foundation)
 28   __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ (in CoreFoundation)
 29   __CFRunLoopDoObservers (in CoreFoundation)
 30   __CFRunLoopRun (in CoreFoundation)
 31   CFRunLoopRunSpecific (in CoreFoundation)
 32   RunCurrentEventLoopInMode (in HIToolbox)
 33   ReceiveNextEventCommon (in HIToolbox)
 34   _BlockUntilNextEventMatchingListInModeWithFilter (in HIToolbox)
 35   _DPSNextEvent (in AppKit)
 36   -[NSApplication _nextEventMatchingEventMask:untilDate:inMode:dequeue:] (in AppKit)
 37   -[DVTApplication nextEventMatchingMask:untilDate:inMode:dequeue:] (in DVTKit)
 38   -[NSApplication run] (in AppKit)
 39   NSApplicationMain (in AppKit)
 40   start (in libdyld.dylib)

abort() called

Application Specific Signatures:
NSRangeException

Application Specific Backtrace 1:
0   CoreFoundation                      0x00007fff9993a452 __exceptionPreprocess + 178
1   DVTFoundation                       0x0000000106127762 DVTFailureHintExceptionPreprocessor + 194
2   libobjc.A.dylib                     0x00007fff882b8f7e objc_exception_throw + 48
3   CoreFoundation                      0x00007fff99851725 -[__NSArrayM objectAtIndex:] + 245
4   IDEKit                              0x000000010776c830 -[_IDENavigatorOutlineViewDataSource outlineView:child:ofItem:] + 190
5   AppKit                              0x00007fff86d092e5 refreshRowEntryItemAndLevelInfo + 327
6   AppKit                              0x00007fff86d02f67 -[NSOutlineView reloadItem:reloadChildren:] + 3024
7   IDEKit                              0x0000000107767d7b -[IDENavigatorOutlineView reloadItem:reloadChildren:] + 357
8   IDEKit                              0x000000010776ac2e __83-[_IDENavigatorOutlineViewDataSource _processNavigableItemGraphChangeNotification:]_block_invoke.735 + 522
9   DVTKit                              0x000000010685464f +[NSAnimationContext(DVTNSAnimationContextAdditions) dvt_nonAnimatedBlock:] + 132
10  IDEKit                              0x0000000107765441 -[IDENavigatorOutlineView suspendEditingWhilePerformingBlock:] + 101
11  IDEKit                              0x000000010776a76d -[_IDENavigatorOutlineViewDataSource _processNavigableItemGraphChangeNotification:] + 2226
12  DVTFoundation                       0x0000000106127576 DVTInvokeWithLazyFailureHint + 100
13  DVTFoundation                       0x00000001060e1f32 __48-[_DVTNotificationReceiver receiveNotification:]_block_invoke.42 + 149
14  DVTFoundation                       0x00000001060e1c7f -[_DVTNotificationReceiver receiveNotification:] + 1054
15  CoreFoundation                      0x00007fff998c5b1c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
16  CoreFoundation                      0x00007fff998c5aaf ___CFXRegistrationPost_block_invoke + 63
17  CoreFoundation                      0x00007fff998c5a27 _CFXRegistrationPost + 407
18  CoreFoundation                      0x00007fff998c5792 ___CFXNotificationPost_block_invoke + 50
19  CoreFoundation                      0x00007fff99882542 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1922
20  CoreFoundation                      0x00007fff99881795 _CFXNotificationPost + 693
21  Foundation                          0x00007fff9718e17a -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
22  DVTFoundation                       0x00000001060e338a -[NSNotificationCenter(DVTNSNotificationCenterAdditions) _dvt_postNotificationName:object:userInfo:] + 360
23  IDEKit                              0x000000010794c00f -[IDENavigableItemCoordinator _postNotificationNamed:forChangedItems:] + 542
24  IDEKit                              0x000000010794c35d -[IDENavigableItemCoordinator _delayedPostGraphAndPropertyChangeNotifications] + 713
25  DVTFoundation                       0x0000000105ef15a8 __48-[DVTDelayedInvocation initWithTarget:selector:]_block_invoke + 79
26  DVTFoundation                       0x0000000105ef298b -[DVTDelayedInvocation runBlock:] + 257
27  Foundation                          0x00007fff9726884a __NSFirePerformWithOrder + 339
28  CoreFoundation                      0x00007fff998cefc7 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
29  CoreFoundation                      0x00007fff998cef37 __CFRunLoopDoObservers + 391
30  CoreFoundation                      0x00007fff998ae408 __CFRunLoopRun + 872
31  CoreFoundation                      0x00007fff998ade38 CFRunLoopRunSpecific + 296
32  HIToolbox                           0x00007fff87c2b935 RunCurrentEventLoopInMode + 235
33  HIToolbox                           0x00007fff87c2b76f ReceiveNextEventCommon + 432
34  HIToolbox                           0x00007fff87c2b5af _BlockUntilNextEventMatchingListInModeWithFilter + 71
35  AppKit                              0x00007fff869a2df6 _DPSNextEvent + 1067
36  AppKit                              0x00007fff869a2226 -[NSApplication _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 454
37  DVTKit                              0x00000001066d1eaf -[DVTApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 396
38  AppKit                              0x00007fff86996d80 -[NSApplication run] + 682
39  AppKit                              0x00007fff86960368 NSApplicationMain + 1176
40  libdyld.dylib                       0x00007fff94a015ad start + 1
41  ???                                 0x0000000000000001 0x0 + 1

위와 같은 콜스택을 뿜으며 빌 Xcode 서 앱을 빌드 하다가 크래쉬가 발생하면서 비정상 종료 하고 다시  Xcode를 실행 시키면 실행 바로 크래쉬 되어  Xcode 수행이 어려운 경우

이런 경우
rm -rf ~/Library/Developer/Xcode/DerivedData



위 명령을 수행하여 Xcode를 수행 가능 하게는 할 수 있으나
다시 빌드를 하면 또 비정상 종료 되는 경우가 있다.

이런 경우 해결 방법

1.  Product -> Scheme -> Manage Scheme 
에서 새로운 빌드 스킴을 만들고 이전 빌드 스킴 대신 사용해본다.

위와 같이 해도 크래쉬가 발생하면

Pod 로 서드 파티 라이브러리를 이용하고  .xcworkspace를 사용중이라면
다음의 절차를 수행 한다.

프로젝트. xcworkspace파일을 과감하게 삭제 하고
pod install 명령으로 새로 .xcworkspace를 생성 하여 xcode를 새로 생성된 xcworkspace
파일로 시작 하고 빌드 한다.

2016년 12월 21일 수요일

마크다운 편집기로 MS VisualStudio Code가 짱이닷!




마크다운 편집기로서
M$ visual studio code가 최고닷!

확장자 md로 설정하고 미리보기를 클릭 한 다음 좌우로 화면을 분할 하면
입력과 동시에 미리 보기가 보여주기 때문에 최고의 툴 이라 할 수 있겠다.


2016년 12월 10일 토요일

XCode 8.x "No such module error"

Xcode 8.x의 버그로 생각 된다.

Xcode 8 로 버젼 업이 되면서 swift 2.3 / 3.0으로 컨버팅 개고생을 당하고
이용하는 pod 라이브러리 업데이트 까지 아주 개고생을 시키고

하루에 20번 정도에 크래쉬를 경험 하여 짜증이 많이 나는데

어느날 갑자기  No such module error가 난다.

계속 참조 하고 있던 모듈인데....

이런 경우 아래의 스텝 으로 처리 시도를 하였으나 소용이 없다.

xcode 종료

pod cache clean

pod deintegrate || rm -rf Pods

rm -rf ~/Library/Developer/Xcode/DerivedData

xcode 재시작

clean
build

이렇게 하여도 계속 되는 이유 없는 에러가 속출 된다면

다음에 방법을 써보는 것도 좋다.

왼쪽 상단에  New scheme 클릭 또는 Product -> Scheme -> New schem 메뉴

이렇게 새로운 컴파일 스킴을 추가 한다.

그리고 새로운 컴파일 스킴으로 build 한다.

나의 경우는 마법처럼 모든 에러가 사라 졌다.






2016년 10월 26일 수요일

trobleshooting installation issue with CocoaPods

CocoaPods

http://mtsparrow.blogspot.kr/2016/03/cocoapod.html

github에서 좋은 오픈소스를 찾아 iOS프로젝트에 추가 하려고 하면
CocoaPods을 주로 사용 했다.

 프로젝트에 프레임워크를 추가 하기 좋긴 한대 가끔 이게 문제가 생기고
이유 없는 빌드 에러를 만들어 내면 남감 하다.

Xcode에서 이유없는 빌드 에러를 만나거나 오동작 할때는 가끔씩
rm -rf ~/Library/Developer/Xcode/DerivedData

여기를 정리 하곤 한다.

CocoaPods 도 무언가 오동작을 하거나 계속되는 이유없는 빌드 에러를 만날때 
해볼 만한 방법은

pod cache clean frameworkName1
pod cache clean frameworkName2
pod cache clean frameworkName3
pod cache clean frameworkName4
pod deintegrate || rm -rf Pods
pod install --verbose
rm -rf ~/Library/Developer/Xcode/DerivedData


요즘은 Carthage 를 많이 사용하는 것 같다.

하지만 아직 사용방법을 모른다.

나중에 새로운 프로젝트를 시작 할때는 참조 프레임워크를 Carthage로 추가 해봐야 겠다.

2016년 10월 23일 일요일

2007 mid mac mini ubuntu install




요약 :
우분투 32비트 설치를 위한 USB부팅 이미지를 만든다.
efi/boot/boot.iso

우분트 32비트 설치 이미지를 boot.iso로 이름을 변경해서 mac mini에 USB를 꽂은 다음 alt (option) 키로 부팅 하면
부팅 디스크 설정에서 usb선택시 32비트 우분투를 설치 할 수 있다.

설치 중간에 boot-repair를 이용해서 부트를 수정 하여 이제 옵션 키를 누르지 않고 바로 부팅이 가능하게 만든다.
다시 usb로 부팅해서 파티션을 나눈다. 32비트 우분투는 20기가 정도 설정한다.

UNetbootin 을 32비트 우분트에 설치해서 64비트 우분트를 내려 받고 설치 한다.


아래에 링크를 따라 하면 설치 할 수 있다.

http://digiecologist.blogspot.kr/2015/12/installing-ubuntu-on-2007-mac-mini-a1176.html


아래의 내용은 따라 하면 에러가 난다.
sudo add-apt-repository ppa:yannubuntu/boot-repair && sudo apt-get update
sudo apt-get install -y boot-repair
boot-repair

이과정에서 key 에러가 나면
http://askubuntu.com/questions/308760/w-gpg-error-http-ppa-launchpad-net-precise-release-the-following-signatures

The link above provides detailed explanation with screenshots. It also has some other simple methods that could be tried before doing this manually. Since it is not accessible from some regions let me describe the method that worked for me.

Go to the OpenPGP Public Key Server. There you can enter your key into the Search String field, leaving everything else as is, then click "Search!".
When searching for a key, always prepend 0x to it! This means that, for example, you have to search for 0x6AF0E1940624A220 instead of 6AF0E1940624A220.
Click on the link provided in the pub section. This should take you to page containing the key. The page's heading should be similar to Public Key Server -- Get "0x6AF0E1940624A220"
Copy everything from underneath the title (starting from -----BEGIN PGP PUBLIC KEY BLOCK-----) and save it in a file (e.g. key1).
Once you have the file, run the following command
sudo apt-key add key1

http://keyserver.ubuntu.com
위 내용으로 처리


몇시간 삽질을 하니 이 사이트에 도움되로 잘 설치 된다.
이제 맥미니 2007은 우분트 14.04로 다시 태어 났다.

2016년 10월 1일 토요일

C# FCM 푸시 전송 어플리케이션 만들기

FCM firebase Cloud Message
https://firebase.google.com/docs/cloud-messaging/?hl=ko

GCM에서 FCM으로 변경 되고 있다.

푸시를 전송 하는 것은 구글 사이트에 요청 하면 된다.
결국 http url request 를 하면 되는 것이고 그것을 어떠한 언어로든 구현 하면 된다.

전송되는 메세지는 json 포멧으로 전달 하면 된다.

이런 것을 지원 해주는 앱으로 구글 포스트 맨도 있다.
https://www.getpostman.com

FCM으로 변경되면서 직접 테스트로 push를 발송 해보는 페이지도 있으니 사실 테스트 어플리케이션이나 포스트맨 어플은 필요 없을수도 있다.

하지만 이번에 개발을 하면서 이미 구현된 서버가 C#으로 구현되어 있다.
모바일 앱과 동작 하는 앱서버가 C#으로 구현 되어 있고
여기에 푸시 기능을 추가 하려 하니 당연히 C# 코드가 필요 했다.

https://github.com/UniverseBryan/FCMWinServer

여기 코드를 참고 해서 간단한 윈폼 어플을 개발 해 보았다.

C#언어로 개발 해본 경험이 없지만
아주 생산성이 좋은듯 하다. 그동안 M$ 개발툴을 너무 멀리 하고 있었는데.
최근 파이썬을 비줠스튜디오로 만지면서 비줠스튜디오 커뮤니티 에디션을 조금 만저 봣는데
나름 C#도 생산성이 좋은 언어 인듯 하다.

아래의 코드가 푸시 전송 코드이다.
폼에 텍스트 입력 두개와 버튼 하나를 언지고
git에서 어든 dll파일을 추가해서 참조에 추가 하고 아래의 코드를 폼 코드에 추가 하면 된다.


using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Diagnostics;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string res = SendNotification("app registration token key string 152 bytes here", textBox2.Text);
        }


        public string SendNotification(string deviceId, string message)
        {
            string SERVER_API_KEY = "API KEY STRING";
           
            var value = message;
            string resultStr = "";

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://fcm.googleapis.com/fcm/send");
            request.Method = "POST";
            request.ContentType = "application/json;charset=utf-8;";
            request.Headers.Add(string.Format("Authorization: key={0}", SERVER_API_KEY));

            var postData =
            new
            {
                data = new
                {
                    title = textBox1.Text,
                    body = message,
                },

                // FCM allows 1000 connections in parallel.
                to = deviceId
            };

            //Linq to json
            string contentMsg = JsonConvert.SerializeObject(postData);
            Debug.WriteLine("contentMsg = " + contentMsg);

            Byte[] byteArray = Encoding.UTF8.GetBytes(contentMsg);
            request.ContentLength = byteArray.Length;

            Stream dataStream = request.GetRequestStream();
            dataStream.Write(byteArray, 0, byteArray.Length);
            dataStream.Close();

            try
            {
                WebResponse response = request.GetResponse();
                Stream responseStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(responseStream);
                resultStr = reader.ReadToEnd();
                Debug.WriteLine("response: " + resultStr);
                reader.Close();
                responseStream.Close();
                response.Close();
            }
            catch (Exception e)
            {
                resultStr = "";
                Debug.WriteLine(e.Message);
            }

            return resultStr;

        }

    }

   

}