어느날 APK를 생성하니 

 

아래와 같이 에러가 발생 되었습니다.

 

 

자세히 확인해 보니 jcenter()에서 api를 가져오지 못하는것으로 보입니다.

 

그래서

 

build.gradle의 jcenter() 호출하는 부분을 mavenCentral()로 변경 했더니 해결이 되었습니다.

 

As-Is 

문제가 발생된 코드

 

To-Be

해결된 코드

 

위의 To-Be 와 같이 하였을 때도 동일하게 오류가 발생 될경우

jcenter() 호출하는 부분을 하나하나 mavenCentral()로 바꿔 보면 해결되는지 확인하면 될듯 합니다.

728x90
반응형

어느날 맥북에서 

 

ionic prepare android 해서 앱을 실행하니 오류가 발생되어서 터미널에서 생성 과정을 확인하니 

 

오류가 발생되고 있었습니다.

 

잘 확인해보니 www폴더가 생성되었다가 사라지기를 반복하고있더군요...

 

 

그래서 아래와같이 권한을 허용해 주니 잘됩니다.

sudo chmod 755 /Users/.../ionic_project

 

감사합니다.

728x90
반응형

 

아래와 같이 에러가 발생될 경우

 

Caused by: com.android.builder.errors.EvalIssueException: Configuration `:app:debugRuntimeClasspath` contains AndroidX dependencies, but the `android.useAndroidX` property is not enabled, which may cause runtime issues.

 

아래 파일들이 누락되어있는 경우 발생합니다.

gradle-wrapper.properties 파일

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

 

gradle.properties 파일(중요)

@@ -0,0 +1,24 @@
# Project-wide Gradle settings.

# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.

# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html

# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m

# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
728x90
반응형

Angular 버전 10 기준

 

NgStyle, NgClass 에 대해 간단히 서술하고자 합니다.

 

NgStyle (script 단에 isNgStyleChange = false; 선언)

    <h3>NgStyle</h3>
    <div style="width: 100px;height: 100px;"
        [ngStyle]="{background: isNgStyleChange? 'red' : 'yellow',width:isNgStyleChange?'50px':'100px'}"
        (click)="isNgStyleChange = !isNgStyleChange">TextColor</div>

 

결과물

클릭 했을때

위와 같이 style을 동적으로변경해줄수 있다.

 

 

 

NgClass (script 단에 isNgClassChange = false; 선언)

<h3>NgClass</h3>
<div class="home-ngclass" [ngClass]="{on: isNgClassChange}" (click)="isNgClassChange = !isNgClassChange">TextColor2</div>
    
// scss
.home-ngclass {
width: 100px;
height: 100px;
background: yellow;

    &.on {
        background: red;
        height: 50px;
    }
}

결과물

클릭 했을때

 

위와같이 css 클래스를 동적으로 제어할 수 있다.

728x90
반응형

이번에 하나투어 코사무이 패키지 신행을 다녀오면서 일을 기록 및 공유하려고 합니다.
기억나는 대로 쓰는 것이라 사실과 조금 다를 수도 있습니다.
 
환전.
- 약 5000 바트(약 19만 원)하면 충분합니다 (저는 100 10장 나머지는 500밧으로 가져갔습니다.)
- 달러는 거의 필요 없었습니다.
(그나마 쓰는 곳이 호텔인데 1달러 혹은 2달러짜리 팁으로 주는 용도로 씁니다.
저는 약 100달러 가져갔는데 50달러는 현지 가이드 팁으로 주고 약 15달러는 호텔직원에게 팁으로 주고 나머지는 면세점에서 다 썼습니다.)
 
부족한 건 해외에서 사용가능한 신용카드 혹은 체크카드 사용하시면 됩니다.

Tip 1.
토스 현장결재 완전 편합니다.
태국 면세점과 현지 편의점에서 다 사용됩니다. 카드복사 걱정도 없구요. 꼭 사용해 보세요.
(출국전에 카드등록하셔야합니다.)

 
유심
말톡유심 사용하시면 태국에서 스마트폰 인터넷을 편히 사용 가능합니다.
검색창에 "말톡 태국"이라고 검색하면 됩니다.
호텔에서 Wifi 에그를 빌려준다고 얼핏 봤던 거 같은데 저희는 그냥 말톡에서 유심 구매해서 사용했습니다.
저는 S22 이전 모델이라 말톡에서 유심구매해서 사용했는데
최신 모델은 eSim이어서 유심 교체 안해도 되는 것으로 알고 있습니다.
아무튼 유심 교체 할 줄 아시면 그냥 태국 도착했을때 유심만 갈아 끼면 폰으로 계속 인터넷 사용가능합니다.
저는 아래와 같이 구입하였습니다.

https://smartstore.naver.com/dial070/products/2191726720?NaPm=ct%3Dlxfxarag%7Cci%3D1ddf396270c416232e2c55a608babd0739f12820%7Ctr%3Dsls%7Csn%3D403132%7Chk%3D6a745dedd3422740263d0f71abc929a7530bb41e

태국유심 방콕 푸켓 5G속도 AIS무제한 핫스팟 통화 유심칩 인천공항수령 7일15GB : 말톡

[말톡] 말톡앱과 해외유심으로 무료통화 인천공항당일구매수령 010수신가능 미국,유럽,베트남,태국유심

smartstore.naver.com

 
준비물.
여권, 신분증, 선글라스, 선크림, 충전기, 충전기케이블, 모자, 들고 다닐 가방, 여벌옷, 수영복,
현지돈(다이소에 파는 미니지퍼백에 넣고 다니니 좋더라고요),
기내용 캐리어(약 20인치 미만), 수하물용 캐리어
- 바다 수영 좋아하시면 스노클링 장비 가져가시는 걸 추천합니다.

Tip 2.
캐리어는 왠만해서 2개를 가져가시는 걸 추천합니다.
면세품 넣거나 그곳에서 쇼핑할 물품을 담기 위해서죠.

 
 
첫째 날
며칠 전에 아래와 같이 문자가 와 있어서 택시를 타고 "인천공항 제2여객터미널"에 갔습니다

<공항 미팅 >    제공  :  일정표 , 티켓
일시 :..월 ..일 오전 06:30
장소 :인천공항 제2여객터미널 3층 출국장 H카운터 옆 여행사 미팅장소 하나투어 테이블

 
 
1. 탑승권 발급
저희는 6시 조금 안되게 도착해서 여행사에서 간단히 안내받고 탑승권 받아서 바로 탑승수속 밟았습니다.
- 저 개인적으로는 패키지여행이라 다른 사람들 기다렸다가 같이 움직이는 건가? 생각하며 바로 갔는데 
여러 여행사들과 그 여행사를 이용하는 사람들이 많더군요.
그 사이를 헤쳐 가며 끝에 쯤 하나투어 직원분? 이 계시더군요. 
탑승권 주면서 간단히 안내해 주고 바로 탑승수속 해도 된다고 하더군요.

Tip 3.
탑승권은 두장을 줍니다.
1. 인천 -> 방콕, 대한항공, 대략 오전 9시 출발 ~ 오후 2시  도착
(첫번째 티켓은 GATE 탑승구 란에 어디서 탑승하면 된다고 잘 나와있습니다.)
2. 방콕 -> 코사무이, 방콕항공, 대략 오후 4시 출발 ~ 오후 5시 30분 도착
( 두번째 티켓은 GATE 탑승구 란 비어져 있습니다. 대신 FLIGHT란에 PG 000으로 표시 되는데
탑승 약 1시간 전에 전광표지판 보시면 어디서 타는지 알 수 있습니다.)

 
이때부터 안내받은 내용을 토대로 알아서 탑승수속을 진행하면 됩니다.
 
 
2. 수하물 위탁
태국 코사무이 가는 경로는 아래와 같은 과정을 거치는데요.
인천 ->방콕 , 방콕 ->코사무이
 
수하물의 경우 중간(방콕)에서 찾을 필요 없이 바로 코사무이로 이동되더라고요. 
그래서 바로 필요한 물품은 기내용 캐리어 혹은 본인이 잘 가지고 있어야 합니다.

Tip 4.
아래 물품들은 본인이 가지고 있는것이 좋습니다.
목배게, 충전기, 충전기 케이블, 여권, 신분증, 보조배터리, 썬크림, 화장품 등등
- 기내용 캐리어에 액체류는 넣지 않는 것이 좋아요. (액체는 100ml 미만 가능)
ex. 치약, 삼푸, 폼클렌징 등등의 세면도구들 

- 담배피시는 분은 라이터를 본인이 가지고 있어야합니다. (담배피는 공간과 피는 시간 많아요)

 
저희는 직원에게 물어가며 수하물 위탁 하였습니다.
 
 
3. 보안검색
별건 없었고요 그냥 줄도 길고, 기다림이 길었습니다.
 
면세점
보안 검색 후 보이는 공항 면세점 풍경은 기분을 참 좋게 합니다.
면세품은 솔직히 비싼 물품 아니면 그냥 인터넷에서 사는 게 싸더군요.
담배는 확실히 시중보다 무조건 쌉니다.
- 전담 피시는 분이시고 전담 안 가져오셨으면 1MG 담배라도 이때 사시는 걸 추천합니다.
(태국 담배는 1MG 찾기 어려워요ㅠㅠ)
 
 
4. 항공기 탑승

 


드디어 항공기 탑승!!!
이때 자리에 앉아서 핸드폰 충전하려고 하는데 제 케이블이 이상한지 충전이 잘 안 되더군요;;
좌석 head 쪽 태블릿에서 영화를 보며 시간을 보냈습니다.
영화는 정말 최신영화가 많더군요. 보통 이런 건 되게 오래된 영화가 있거나 그러던데;
중간에 밥도 줍니다. 닭고기 커리와 제육쌈밥 중 고르라고 하셔서 저는 닭고기 커리 선택해 먹었습니다.
(맛은 둘 다 좋았습니다.)
영화도 보고 잠도 자고 밥도 먹으니 어느새 방콕공항에 도착!
 
 
5. 방콕 수안나품 공항
항공기에서 내리니 아마 E1~E10였던 것 같은데 아무튼 내리고 엄청 걸었습니다.
전광판을 보니 탑승하는 곳이 A6이었거든요.
가다가 보이는 직원에게 물어서 방콕항공 입구 같은 곳을 통과하고 가다 보면 A B C 교차되는 사거리에 작게 식당가가 있는데 딱히 살건 없었습니다. 

저희는 혹시 다른 면세점 없나 싶어서 돌아다녀 봤는데... 결론은 "네 없습니다."
방콕 -> 코사무이는 국내선(태국 내에서 이동)이라 A B C 교차되는 사거리에 작게 있는 식당가가 쇼핑할 수 있는 유일한 곳입니다. 
저희도 처음에 이렇게 작게 있을 리 없어하면서 엄청 돌아다녔는데 신혼여행 끝나고 돌아오는 길에 깨달았습니다.
국내선에 면세점 없다고 실망하지 마세요. 여행 끝나고 한국 가실 때 방콕공항 국제선 면세점이 얼마나 큰지 알게 되실 겁니다.

Tip 5.
A1~A6 방향으로 가다 보면 방콕항공 라운지 있습니다. 무료로 이용가능합니다.

어느정도 돌아다니고 전광판에 PG 000은 A1에서 타라고 해서 그쪽으로 가서 코사무이로 이동했습니다.
 
 
6. 코사무이
코사무이에서 수하물 캐리어 찾고(짐 찾는곳이 두군데 입니다) 출구로 가서 가이드를 만났습니다.
- 코사무이에 도착하고 바로 짐을 찾으려고 했는데 짐이 계속 안나오는 겁니다;
갑자기 직원이 다가오더니 뭐라고 얘기하는데 처음에 무슨말이지? 하다가 생각해보니 다른곳에서 받아야한다고 하더군요. 다른 한국분들도 그리로 다 이동하구요. 짐 찾는곳이 두군데 였어요ㅠ
아무튼 짐을 찾고 출구쪽으로 계속 가다보면 저희 이름이 쓰여진 피켓을 들고 계신분이 있더군요. 
바로 그쪽으로 가서 가이드 만나서 같이 이동했습니다.
 
7. 일정 확정
가이드 차를 타고 우선 호텔에 가서 체크인을 했습니다. 저희는 리츠칼튼 호텔에서 계속 있었습니다.
그 뒤 음료수 마시는 곳으로 이동해서 일정에 대해 논의 했습니다.
음료수(코코넛 쉐이크)를 사주시면서 1일차,2일차... 5일차의 각 일정들을 확정짓는 의논을 하게 됩니다.
참 옵션들이 많더군요... 추가는 본인 선택...
 
일정의논이 끝나면 저녁식사 선택지가 아래처럼 있는데 저희는 태국식을 골랐습니다.
1. 태국식 샤브샤브의 진수 MK 수끼
2. 산뜻한 일식세트
3. 세계 5대푸드 오리엔탈 타이식
4. 무제한으로 즐기는 삼겹살 & 한식
5. 정통 이태리의 맛을 즐길수 있는 피자 & 파스타
 
아래사진이 태국식 입니다.

어느정도 먹은 후 가이드와 함께 차웽으로 이동합니다.

Tip 6.
- 맥주는 레오, 싱하, 창 이 보통 먹는 맥주인데요 한번씩 먹어보면서 자신에게 맞는 맥주를 찾아보세요.
- 맥주값은 할인마트에서 37밧, 편의점은 40~50밧, 음식점에서 70~255밧 정도 합니다. 

 
8. 차웽
가이드가 차웽거리를 한바퀴 돌며 간단히 설명해줍니다. 이곳은 트랜스젠더 BAR이고 몇시쯤 공연하고, 이곳은 수영장 딸린 BAR 이고, 이곳은 봉춤 추는곳이라고 하고 등등...
그리고 처음 거리가 시작되는 곳에 내려줍니다.

 
대충 아래 그림대로 돌아다니면 됩니다.

 
나중에 쇼핑하실때 이곳에서 하시는걸 추천합니다. (엄청 커요)
https://www.google.co.kr/maps/place/Central+Samui/@9.5322897,100.0607752,3a,75y,90t/data=!3m8!1e2!3m6!1sAF1QipOiNWpgz0kjgcz2uDVinkO5pPOYcAL3raDSirTi!2e10!3e12!6shttps:%2F%2Flh5.googleusercontent.com%2Fp%2FAF1QipOiNWpgz0kjgcz2uDVinkO5pPOYcAL3raDSirTi%3Dw129-h86-k-no!7i1568!8i1038!4m7!3m6!1s0x3054f1cb326356dd:0x70c4badc99f86bbf!8m2!3d9.5322247!4d100.060913!10e5!16s%2Fg%2F1ym_l6tqs?hl=ko&entry=ttu

Central Samui · 209 209/1-2 หมู่ที่ 2 ตำบล บ่อผุด Tambon Bo Put, Ko Samui District, Surat Tha

★★★★☆ · 쇼핑몰

www.google.co.kr

 
저희는 돌아다니다가 그냥 음식점 들어가서 모닝글로리(엄청 맛남)와 고기나 새우같은거 먹으면서 맥주 마셨어요.
그러다가 트젠 바 가서 구경도 하구요
트젠 바에서는 트랜스젠더가 노래크게 틀고 립싱크하는거 보면서 맥주 먹었습니다.
(입장료 인당 약 300밧인데 음료 1개값도 포함되어있습니다)
 
그리고 돌아가실때 11시 전이라면 Central Samiui 안에 Tops라고 엄청 큰 대형 마트 있습니다. 
거기서 술이나 안주류 사서 호텔로 가시면 됩니다.
(저희가 갔을때는 영업시간이 대략 오전 10시~ 오후 11시로 듣긴했는데 혹시모르니 오후 10시 전에 가시는걸 추천합니다.)
 
저희는 Tops 마트 존재를 몰라서 근처 편의점에서 개당 약 50밧 주고 맥주 구입해서 택시타고 리츠칼튼 호텔로 이동해서
하루를 마무리 했습니다.

Tip 7. 차웽에서 리츠칼튼 호텔까지 택시비는 어느정도(300~500밧)가 적당하다고 가이드한테 들을겁니다.
흥정하는 방법도 대략 가이드한테 들을 수 있을겁니다.

 
감사합니다.
 
두번째날은 다음글에 작성하겠습니다.

728x90
반응형
	// Json형식으로 바꿀 데이터
        let arr: Array<Dictionary> = [
            [
                "name":"이름1",
                "email":"mail1@naver.com"
            ],
            [
                "name":"이름2",
                "email":"mail2@naver.com"
            ],
            [
                "name":"이름3",
                "email":"mail3@naver.com"
            ]
        ]
        
        // json으로 변환된 String
        var jsonObj : String = ""
        do {
            let jsonData:Data = try JSONSerialization.data(withJSONObject: arr, options: .prettyPrinted)
            
            // json 데이터를 변수에 삽입 실시
            jsonObj = String(data: jsonData, encoding: .utf8) ?? ""
        } catch {
            print(error.localizedDescription)
        }
        print("jsonObj : " , jsonObj)

결과값

 

728x90
반응형

 

특정 URL로 통신하니 

java.io.IOException: Cleartext HTTP traffic to test.tlshenm.com not permitted 오류가 발생되었습니다.

안드로이드 파이(9)부터 Http 통신시 발생된다고 하더군요...

해결방법

Https 통신으로 바꾸거나 바꿀수 없으면 허용을 해줘야 합니다.

저는 허용하는 방법을 안내하겠습니다.

 

1. res/xml폴더를 생성하시구요

2. res/xml/network_security_config.xml파일을 생성합니다.

3. 아래그림과 같이 예외처리할 URL(test.tlshenm.com)을 넣어 줍니다.

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">localhost</domain>
        <domain includeSubdomains="true">test.tlshenm.com</domain>
    </domain-config>
</network-security-config>

마지막으로 AndroidManifast.xml안에 <application> 태그안에 아래 코드를 넣어 줍니다.

    <application
        android:networkSecurityConfig="@xml/network_security_config"
        . . . . . .>

이제 빌드해보시면 정상적으로 동작되실겁니다.

728x90
반응형

오랜만에 새로운 버전으로 빌드해보니 오류가 발생되었습니다.

Installed Build Tools revision 31.0.0 is corrupted. Remove and install again using the SDK Manager.

 

31 SDK를 설치해도 동일하게 발생되더군요.

 

해결방법

SDK를 30으로 낮춘다...

(나중에 31로 플레이스토어에 배포하라 그러면 어쩌라는 거냐...)

그림과 같이 바꾸시면 됩니다.

그럼 빌드 되실겁니다.

728x90
반응형

IONIC 백버튼 관련하여 얘기해보려합니다.

 

각 페이지 별로 백버튼을 subscribe 할수도 있겠지만

 

필자의경우 app.component에서 다 처리하는 편입니다.

로직은 아래와 같으며, 홈화면에서 다른 화면이동시 백키동작이 됩니다.

 

기본 안드로이드 Back Key 처리로직

import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { Platform, ToastController } from '@ionic/angular';

declare var window: any;

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss'],
})
export class AppComponent {
  private  backPressCount = 0;  // 백버튼 카운트


  constructor(
    private router: Router,
    private platform: Platform,
    private toastCtrl: ToastController

  ) {
    this.platform.backButton.subscribeWithPriority(1, () => { // to disable hardware back button on whole app
      console.log("백버튼 호출");
      window.history.back();
    });
  }

위의 로직에서

 

추가적으로 홈화면에서 앱종료를 시켜주고 싶을땐

우선 선행작업이 필요합니다.

1.

npm i cordova-plugin-exit

위 명령어를 콘솔창에 입력하여 모듈을 import 해야합니다.

 

cordova-plugin-exit

Cordova plugin for exiting the app programmatically for Android, iOS and WP

www.npmjs.com

2.

로직을 입력합니다.

안드로이드 백키 앱종료 로직

import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { Platform, ToastController } from '@ionic/angular';

declare var window: any;

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss'],
})
export class AppComponent {
  private  backPressCount = 0;  // 백버튼 카운트


  constructor(
    private router: Router,
    private platform: Platform,
    private toastCtrl: ToastController

  ) {

    this.platform.backButton.subscribeWithPriority(1, () => { // to disable hardware back button on whole app
      console.log("백버튼 호출");
      if (this.router.url === '/home') {
        if (this.backPressCount > 0) {
          window.cordova.plugins.exit();
        } else {
          this.backPressCount++;
          this.presentToast('한번 더 누르시면 App이 종료됩니다.');
          setTimeout(() => {
            this.backPressCount = 0;
          }, 5000);
        }
      } else{
          window.history.back();
      }
    });

  }

  async presentToast(str) {
    const toast = await this.toastCtrl.create({
      message: str,
      duration: 5000
    });
    toast.present();
  }
}

*참고사항 

아이오닉 자체 오류인 것같은데 앱 실행시 즉각적으로 백키로직이 동작되지는 않습니다... 

다른화면으로 이동하면 그때 적용됩니다... 왜 그런지는 저도 찾아보고있습니다...

아시는분은 댓글좀....

 

 

추가적으로 백키 방지로직 공유드립니다.

안드로이드 백키 방지 로직(매우 간단합니다 로직처리를 안하면됩니다.)

import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { Platform, ToastController } from '@ionic/angular';


declare var window: any;

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss'],
})
export class AppComponent {
  private  backPressCount = 0;  // 백버튼 카운트

  constructor(
    private router: Router,
    private platform: Platform,
    private toastCtrl: ToastController

  ) {
    this.platform.backButton.subscribeWithPriority(1, () => { // to disable hardware back button on whole app
      console.log("백버튼 호출");
      if (this.router.url === '/home') {
        if (this.backPressCount > 0) {
          window.cordova.plugins.exit();
        } else {
          this.backPressCount++;
          
          setTimeout(() => {
            this.backPressCount = 0;
          }, 5000);
        }
      } 
      else{
        // 로직 처리를 안하면 백키가 동작되지 않습니다.
        // 이곳에 전역적으로 사용하는 boolean값을 추가하여 백키동작을 컨트롤 하시면되겠습니다.
        // (ex)
        // if(isBackKeyBlock) {
        //   window.history.back();
        // }
      }
    });
  }

  async presentToast(str) {
    const toast = await this.toastCtrl.create({
      message: str,
      duration: 5000
    });
    toast.present();
  }
}

 

728x90
반응형

'IONIC' 카테고리의 다른 글

npm 설치시 터미널 이슈  (0) 2021.09.01

변수는 알아봤으니 국룰로 다음은 배열을 알아봐야겠지요.

 

배열 2.1

배열도 자바와 거의 비슷합니다.

변수명을 앞에 선언하고 타입을 뒤에다 선언하시면 되겠습니다.

 

let strArr:string[] = ["가",'나','다','라','마','바'];

let numArr:number[] = [1,2,3,4,5,6,7,8];

let boolArr:boolean[] = [true,false,true,false];

let anyArr:any[] = ["가",1,true,"나",2,false];

 

관련API

배열 또한 모질라 html 가이드 문서가 넘나 잘되어있어서 링크만 붙이겠습니다.

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array

 

Array - JavaScript | MDN

JavaScript Array 전역 객체는 배열을 생성할 때 사용하는 리스트 형태의 고수준 객체입니다.

developer.mozilla.org

 

728x90
반응형

'IONIC > TypeScript' 카테고리의 다른 글

TypeScript 기초#1  (0) 2021.10.21

간단하게 타입스크립트 기초를 쓰려고합니다.

 

저는 자바개발자였기때문에 자바개발자기반으로 설명 하도록 하겠습니다.

 

1.1 변수

타입스크립트는 거의 자바와 동일합니다.

  • int -> number
  • String -> string
  • boolean -> boolean

이렇게 쓰고 있습니다.

보통 쓰는 타입들은 

  • String : 문자열
  • number : 숫자
  • boolean : true, false (참 혹은 거짓)
  • any : 모든 타입과 호환됩니다.(자바에서 Object객체같기도...)

참고사항

타입스크립트는 자바스크립트와 비슷하게 var, const, let이 있습니다.

간단하게 const는 상수로 보시면 되고 var와 let이 비슷한데 

보통 저같은경우에는 let을 씁니다.

아래 코드를 보시면 조금은 이해되실수도...

var a = 1;
let b = 1;
test();
test1();

function test(){
  // 결과값이 3으로 노출
   var a =2;
   var a =3;
   console.log(a);
}

function test1(){
  // 오류를 발산
  let b =2;
  let b =3;
  console.log(b);
}

간단히 설명 드리자면

var는 test()메서드 안에 여러번 같은 변수를 선언해도 오류가 나지 않습니다.

let은 test1()메서드 안에 여러번 같은 변수를 선언하면 IDE에서 오류를 노출시킵니다.(자바와 거의 동일하죠)

 

사용 예

let num:number = 10;
let str:string = "하이";
let bool:boolean = true;

// any의 경우 안의 내용에 따라 타입이 정해집니다.
let anyString:any = "안의 내용의 따라 타입이 정해집니다.";
let anyNumber:any = "20";
let anyBool:any = true;

솔직히 any 저는 좋았습니다. 특히 공통으로 쓸 메서드 만들거나 모듈을 만들때 넘나 좋아요~!

 

변수 API 

솔직히 제가 설명할 필요없이 파이어폭스(모질라)에서 만든 html 가이드가 넘나 잘 되어있어서

관련 링크만 붙이겠습니다.

 

number관련 API

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Number

 

Number - JavaScript | MDN

Number 객체는 숫자 값으로 작업할 수 있게 해주는 래퍼(wrapper) 객체입니다. Number 객체는 Number() 생성자를 사용하여 만듭니다. 원시 숫자 자료형은 Number() 함수를 사용해 생성합니다.

developer.mozilla.org

string 관련 API

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String

 

String - JavaScript | MDN

String 전역 객체는 문자열(문자의 나열)의 생성자입니다.

developer.mozilla.org

boolean 관련 API

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Boolean

 

Boolean - JavaScript | MDN

Boolean 객체는 불리언 값을 감싸고 있는 객체입니다.

developer.mozilla.org

그 외에도 Date, JSON을 조금 보시는 걸 추천합니다.

 

728x90
반응형

'IONIC > TypeScript' 카테고리의 다른 글

TypeScript#2  (0) 2021.10.21

문제

맥북을 쓰다보면 포맷을 할때가 있다.

 

그럴때는 새로 환경설정을 해줘야하는데 이게 참 골치가 아프다.

 

(구글링 해보니 .profile해주면 된다는 데 맥OS 카탈리나 이상은 안된다.)

 

node.js를 설치 후에

"npm -v", "node -v" 하면 버전정보가 잘 보인다.

 

npm i -g OOO 이라고 써보면 해당 터미널에서는 잘 설치되었지만 

명령어를 입력해보면 아래와 같이 나온다.

 

zsh: command not found:OOO

 

 

해결방법(맥북 OS 카탈리나 이상만)

아래 순서대로 터미널에 입력해보자

mkdir ~/.npm-global

 

npm config set prefix '~/.npm-global'

 

nano ~/.zprofile

 

// (편집기에서 아래 내용을 그대로 추가 후 저장)
export PATH=~/.npm-global/bin:$PATH

contorl + o  // 저장

control + x  // 편집기 종료

(확인사항)
// nano ~/.zprofile  명령어 입력시 A-1 이미지 처럼 나오면 성공
// control + x 키를 눌러 빠져나오자
A-1

 

// 마지막 설정을 저장해주면 된다.
source ~/.profile

 

 

자 이제 맥북을 껏다가 켜도, 새로운 터미널을 켜도

설치된 모듈 버전을 가져오는 것을 볼수 있다.

728x90
반응형

'IONIC' 카테고리의 다른 글

IONIC 백버튼  (0) 2021.10.24

안드로이드 소스를 비교하는 방법에 대해 설명드리도록 하겠습니다.

 

 

우선 프로젝트를 먼저 실행해 줍니다.

 

저는 예시로 OldProject 와 NewProject를 소스를 비교할겁니다.

 

1. OldProject를 안드로이드 스튜디오로 실행 시켜 줍니다.

2. OldProject에서 아래와 그림과 같이 비교할 특정폴더(OldProject/app/main)를 선택합니다.

 

3. 마우스 오른쪽 클릭하여 메뉴를 엽니다.

4. 메뉴 중 Compare With를 선택합니다.

 

5. 비교할 프로젝트의 소스 폴더를 선택후 Open 버튼을 누릅니다.

예시)

OldProject/app/main

NewProject/app/main 선택

 

6. 짜잔~! OldProject/app/main과 NewProject/app/main의 소스파일들이 비교됩니다.

이런식으로

안드로이드 스튜디오에서 비교하면 어떤 소스가 추가 되었는지 또 어떤 소스가 없어졌는지 명확히 알수 있습니다.

 

728x90
반응형

안드로이드 백버튼 두번 누른 후 앱 종료동작


public class MainActivity extends Activity {
private Context mContext = null;
private long backKeyPressedTime = 0;


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mContext = this;
}

@Override
public void onBackPressed() {
if (System.currentTimeMillis() > backKeyPressedTime + 2000) {
backKeyPressedTime = System.currentTimeMillis();
Toast.makeText(this, "\'뒤로\'버튼을 한번 더 누르시면 종료됩니다.", Toast.LENGTH_SHORT).show();
return;
}
if (System.currentTimeMillis() <= backKeyPressedTime + 2000) {
super.onBackPressed();
}
}



728x90
반응형

아래와 같이 에러가 발생하였을때


ERROR: Unable to find method 'org.gradle.api.tasks.compile.CompileOptions.setBootClasspath(Ljava/lang/String;)V'.

Possible causes for this unexpected error include:

Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.)

Re-download dependencies and sync project (requires network)


The state of a Gradle build process (daemon) may be corrupt. Stopping all Gradle daemons may solve this problem.

Stop Gradle build processes (requires restart)


Your project may be using a third-party plugin which is not compatible with the other plugins in the project or the version of Gradle requested by the project.


In the case of corrupt Gradle processes, you can also try closing the IDE and then killing all Java processes.



해결방법


Project/gradle/wrapper/gradle-wrapper.properties 파일로 들어가서

5.1.1부분을 4.6이라던지 4.1로 버전을 변경해보시면 정상 빌드 되실겁니다.


그래도 안되시면 

안드로이드 스튜디오를 종료후 재시작 해보시거나

File/Sync Project with Gradle File를 눌러 보시기 발랍니다.




728x90
반응형

안드로이드 특수문자 체크로직은 아래와 같습니다.

private static void 특수문자_테스트() {
// TODO Auto-generated method stub
String str = "ttt";
if(str!=null && str.matches("[0-9|a-z|A-Z|-|-|-| ]*")) {
System.out.println("특수 문자가 없습니다.");
}else {
System.out.println("특수문자가 있습니다.");
}
}

만약 특정 특수문자도 허용하고 싶을경우 아래와 같이 할 수 있습니다.

필자의 경우 앱을 만들때 아래와 같이 체크로직을 만들었다.

private static void 문자열_체크() {
// TODO Auto-generated method stub
String str = "ttt";
if(str!=null && str.matches("[0-9|a-z|A-Z|-|-|-|@\\-\\_\\.\\;\\·\u318D\u119E\u11A2\u2022\u2025a\u00B7\uFE55]*")) {
System.out.println("허용되는 문자열입니다.");
}else {
System.out.println("허용되지 않은 문자열 입니다.");
}
}

유니코드(\u318D\u119E) 를 쓴 이유는 한글의 경우 천지인 키보드의 아래아 ‘·(middle dot)’ 를 이용하기 때문에, 이를 허용하여야 하는데 위의 UniCode 들은 여러 제조사(삼성, LG, 팬택 등)의 단말기들에서 아래아 ‘·(middle dot)’ 표현하는 값이다. 




728x90
반응형

'Java' 카테고리의 다른 글

자바 랜덤  (0) 2017.05.23
java 정렬  (0) 2017.05.23
java 파일용량 계산  (0) 2017.05.23
액티비티 할당된 메모리 즉시 반환하기  (0) 2016.01.12
Java Null Check 코드  (0) 2015.06.29

곧 안드로이드 스튜디오 build.gradle  compile 명령어가 Deprecated 된다고 합니다.

대신 implementation, api 명령어로 모듈을 import할 수 있습니다.



728x90
반응형

*요약 

- 이제 findViewById()를 쓸 필요가 없다


기존에는 xml에 id를 선언하고 해당 ui를 컨트롤 하기 위해서는 클래스에 findViewById()를 무조건 해줬습니다.

다음과 같이 말이죠


activity_main.xml

<android.support.constraint.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
>

<TextView
android:id="@+id/tv_ShowText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/btn_GetData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="getDataButton" />

</android.support.constraint.ConstraintLayout>

MainActivity.java

private TextView mShowText = null;
private Button mGetBtn = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mShowText = (TextView) findViewById(R.id.tv_ShowText);
mGetBtn = (Button) findViewById(R.id.btn_GetData);
}

지금은 ui가 Text와 Btn밖에 없기 때문에 findViewById()를 2번만 선언하였습니다.

하지만 앱이 복잡해지고 ui 컴포넌트가 많아질경우 findViewById는 얼마나 많이 선언해줘야 할까요?



다음과 같이 개선된 방식을 사용하면 일일이 findViewById를 선언해 주지 않아도 됩니다.

1. 앱 단위 build.gradle에 dataBinding을 선언해 줍니다.

dataBinding {
enabled = true
}


2.layout xml 최상위 루트에 <layout> 태그를 넣어 줍니다.

<layout xmlns:android="http://schemas.android.com/apk/res/android"></layout>
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

<android.support.constraint.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
>

<TextView
android:id="@+id/tv_ShowText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/btn_GetData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="getDataButton" />

</android.support.constraint.ConstraintLayout>
</layout>


3.클래스에서는 setContentView(R.layout.activity_main);-> DataBindingUtil.setContentView(this, R.layout.activity_main); 같이 변경해준다.

private ActivityMainBinding mBinding;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
mBinding.tvShowText.setText("바뀐다");
}

*참고 ActivityMainBinding클래스는 실제로 없습니다. 안드로이드에서 자동적으로 만들어 줍니다.

그래서 ReBuild 하기 전까지 오류로 표시될것입니다.

하지만 따라가야할 규칙이 있습니다. 멤버변수 클래스 네임은 xml파일을 따라갑니다. 

activity_main.xml ->    ActivityMainBinding

activity_content.xml ->    ActivityContentBinding

activity_love.xml ->    ActivityLoveBinding

main_act.xml    ->    MainActBinding

love_act.xml    ->    LoveActBinding


*Fragment에서 사용법

fragment_blank.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android">

<FrameLayout xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.damoa.framenttest.BlankFragment">

<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />

<WebView
android:id="@+id/test_webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</FrameLayout>
</layout>

BlankFragment.java

private FragmentBlankBinding mBinding = null;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_blank, container, false);
mBinding.testWebview.loadUrl("https://www.google.co.kr");

return mBinding.getRoot();
}







728x90
반응형

태블릿을 개발하다보면 새로나오는 태블릿마다 해상도가 깨지는 현상이 발생한다.

DP로 정해줘도 태블릿이 새로나오면 UI가 깨지는 현상이 발생된다.

이유는

1. 해상도가 다르다.

2. DPI가 다르기 때문이다.


아래에 표를 보면 태블릿의 DP해상도는 크게 3개의 크기로 구분 할 수 있을거 같다.

1280 * 800

1024 * 768

960 * 600


*참고1) PX/DPI = DP , DP*DPI = PX

*참고2) smallestWidth(DP)는 가로,세로의 상관없이 가장 적은  비율의 값

*참고 표1 Orientation = LandScape 기준으로 작성

 기종

PX

DPI

  DP

smallestWidth(DP)  

WIDTH 

HEIGHT 

WIDTH 

 HEIGHT

Galaxy Note 10.1 2014 Edition

 2560

1600 

1280 

800 

 800

 Galaxy Note 10.1

 1280

800 

1280 

800 

800 

 Galaxy Tab 10.1

 1280

800 

1280 

800 

800 

 Galaxy Tab  8.9

1280 

800 

1280 

800 

800 

 Galaxy Tab A(2016)

1920 

1200 

1.5 

1280 

800 

800 

 Galaxy Tab S2

2048 

1536 

1024 

768 

768 

 Galaxy Tab A 9.7

1024 

768 

1024 

768 

768 

 Nexus 9 

2048 

1536 

1024 

768 

768 

 Galaxy Tab S3 

 2048

1536 

2.25 

910.2 

682.7 

682.7 

 Galaxy Tab E(W/B)

 1280

800 

1.33

961.5 

600.9 

600.9 

 G Pad3 8.0

 1920

1200 

960 

600 

600 


위에 표를 보았을 때 느낀점은 Galaxy Tab S3는 왜 DPI가 저럴까?;; 필자도 궁금하다.


태블릿마다 해상도가 깨지는 현상이 발생시 수정방법은 여러가지가 있겠지만 그중에 2가지를 들 수 있을거 같다.


방법 1.직접적으로 layout 폴더를 분기 처리한다.

장점

-부분적으로 고치기 딱좋다고 생각된다. UI가 중첩되거나 깨지는 부분만 고치면 되기 때문이다.

단점

-UI가 중첩되거나 깨지는 부분만 고치게 될 경우 UI가 언밸런스 해보일 수 있다.

 

참고 표2

 레이아웃 폴더 분기 종류

 설명

비고 

 layout

 기본레이아웃

 

layout-port

 가로모드시 레이아웃 적용

 

layout-land 

세로모드시 레이아웃 적용 

 

layout-sw600dp 

smallestWidth의 값이 600dp이상일 경우 적용

 1. smallestWidth의 값이 650dp이고 layout-sw600dp, layout-sw651dp폴더가 있을경우 smallestWidth 650dp의 값은 layout-sw600dp에 영향을 받는다.

2. 폴더명 뒤에 -port,-land는 적용 되지 않는다.

 layout-w600dp-port

세로모드의 넓이 dp값이 600이상일 경우 레이아웃 적용

세로모드의 넓이 dp값이 650이고layout-w600dp-port, layout-w651dp-port폴더가 있을경우 650dp의 값은 layout-w600dp-port에 영향을 받는다.

 layout-w600dp-land

가로모드의 넓이 dp값이 600이상일 경우 레이아웃 적용

가로모드의 넓이 dp값이 650이고 layout-w600dp-port, layout-w651dp-port폴더가  있을경우 650dp의 값은 layout-w600dp-port에 영향을 받는다.


방법 2.직접적으로 value폴더의 diman.xml를 분기 처리한다.

장점

-UI를 한꺼번에 고치기 딱 좋다. 깨지는 태블릿의 비율만 계산하여 폴더 분기 처리하면 한꺼번에 적용되기 때문이다.

단점

-비율계산이 잘못될 경우 기존 UI가 망가질수 있다.

참고 표3

-해상도 비율

 해상도

 비율

1280*800 

8:5 

1024*768 

4:3 

960*600 

8:5 









728x90
반응형

안드로이드 앱설치 여부를 확인하기 위해서는 해당앱의 패키지 명을 알고 있어야합니다.


isInstallPackage_2(this,"com.test.pkgname");

/**
* 설치여부를 판단한다
* @param context context
* @param pkgName 패키지명
* @return 설치여부
*/
public static String isInstallPackage_2(Context context, String pkgName){
PackageManager manager = context.getPackageManager();
PackageInfo pi;
try {
pi = manager.getPackageInfo(pkgName, PackageManager.GET_META_DATA);
if(pi!=null){
return pi.versionName+"";
}
} catch (NameNotFoundException e) {
}
return null;
}


728x90
반응형

+ Recent posts