카테고리 보관물: Vue

Nativescript 앱 아이콘 변경 (App Icon)

Nativescript로 앱 개발 시 앱 아이콘은 프로젝트 폴더\App_Resources\Android\src\main\res 아래에 있는 해상도별 아이콘 및 splash 화면 디자인 파일들로 지정되어 있다.

Nativescript의 Default 아이콘을 계속 사용할 수는 없으므로 새로운 아이콘을 지정해 주어야 한다. 그런데 아이콘은 res 폴더 아래에 각 case에 따른 해상도에 맞춰서 제작해 넣어야 하므로 생각보다 뜻대로 안된다.

이 중 mipmap- 으로 시작하는 폴더들이 각 해상도에 맞게 아이콘 파일이 존재해야 하는 폴더들이다.

사이트에 접속해서 아이콘을 올려 놓으면 다양한 해상도에 맞춰서 파일들을 생성해 주므로 그냥 가져다 쓰기만 하면 된다.

아이콘 파일을 Drag&Drop으로 원 위에 올려 놓고 아래 방향으로 된 화살표를 누르면 ic_launcher.zip 파일이 다운로드 된다.

이 다운로드 된 압축 파일을 압축을 풀어 열어보면 res 폴더와 그 아래에 있어야 하는 mipmap- 폴더들이 여러개 존재 한다. 이 폴더들을 그대로 프로젝트 리소스 폴더에 엎어쓰면 되겠다.

(정확하게는 mipmap-xxxhdpi 등의 폴더 내에 ic_launcher.png 파일들과 background용 파일들이 바뀌어 있다 )

그리고 프로젝트를 다시 컴파일 하면 앱의 아이콘이 바뀐 것을 알 수 있다.

Nativescript-vue background-http 설치 후 에러가 나는 경우 -(2)

모바일에서 서버로 post방식 upload 를 하기 위해 이것 저것 다양한 모듈들을 사용해 보았으나 binary file인 image 파일 등을 올리기 위해서는 2022년 10월 현재 axios나 background-http와 같은 library를 추가 설치해야 한다. ( 현재 @nativescript/core에 있는 http를 binary가 가능하게 전환 중이라는 소식이 있으나 현재까지 테스트가 끝나지 않은 것 같아 계속 실패만 했다 ).

axios를 설치하거나 background-http를 설치 한 후 무수한 에러가 발생해서 약 1주일간의 시간을 낭비했다.

결과는 너무 허무했지만 급한 마음에 찬찬히 들여다 보지 않고 급하게 시도하다가 중요한 걸 놓쳤다. 라이브러리를 이해하고 충분히 읽어본 다음 실행했으면 하루만에 모두 성공하지 않았을까 싶다. stackoverflow에도 그 질문 수가 적고 대답을 제대로 하는 경우가 거의 없는 것 보면 어이없는 실수가 아닐까 싶다.

background-http의 기본적인 설치는 다음과 같다.

ns  plugin  add  @nativescript/background-http

2022년 10월 현재 6.0.0 버전이 설치된다. ( 프로젝트 폴더의 package.json 파일을 보고 확인한다 ). 운이 좋으면 바로 실행이 가능하지만 빌드시 에러가 나면 설치를 잘 못했는지 의심하는 마음에 문제를 복잡하게 만들 수 있다. 발생하는 에러는 assembleDebug not found나 application, utils, formdata 등 5개 정도의 변수가 정의되지 않았다고 에러를 낸다.

에러가 발생해서 급한 마음에 설치가 잘못된 건가 하고 npm으로 설치도 해 봤다.

npm install --save nativescript-background-http

이건 버전이 낮은게 깔려서 android sdk와 충돌 또는 호환성 문제를 일으킨다.

nativescript-cli와 버전이 맞지 않는 것 같아 이것도 해 보았다

ns  plugin  add @nativescript/background-http@5.0.2

강제로 낮은 버전을 사용하는 경우 모든 보안 문제나 sdk의 호환성 문제가 더 많이 튀어 나올 수 있다.

1. “assembleDebug” not found in root project [vue_farm] …

가장 시간을 많이 잡아먹게 한 원흉 중 하나이며 어이없는 실수이다. 일단 “assembleDebug”가 없다는 건 어딘가에 뭔가 빠졌다는 느낌인데 뭘 더 설치하려고 하면 문제가 꼬인다. 그리고 가장 흔한 버전 호환성에 의한 문제일 수도 있고 아닐 수도 있어서 더 헷갈린다.

일단 먼저 프로젝트 폴더에서 ns clean으로 지운 다음 다시 빌드/실행 해 본다.

C:\Project\vue\vue-farm> ns clean
- Cleaning project...
√ Cleaned directory hooks
√ Cleaned directory platforms
√ Cleaned directory node_modules
√ Cleaned file package-lock.json
√ Project successfully cleaned.

C:\Project\vue\vue-farm> ns run android

버전 호환성이 의심되어서 background-http를 npm으로 설치하는 바람에 어마어마한 에러들을 맞딱뜨렸다. ㅠㅠ

이 에러가 발생하는 경우는 대부분 버전을 이것 저것 설치하고 제대로 지우지 않고 rebuild하거나 가상 머신 또는 개발 기계에 있는 라이브러리가 충돌해서 발생하는 경우다. 이때는 ns clean을 하고 개발 기계에 있는 앱을 삭제 하고 다시 실행 해 보면 대부분 해결된다.

2. Application not found, File-system not found , … not found….

background-http를 설치하고 난 후 빌드시 약 5개 정도의 라이브러리를 찾을 수 없다고 에러가 발생하는 경우가 있다. 이 경우는 nativescript-background-http를 npm으로 설치하면 해결 되거나 오히려 거꾸로 nativescript-background-http를 npm으로 설치하면 발생하지 않는데 @nativescript/background-http를 설치하면 발생하는 경우가 있다.

두 경우 모두 버전의 문제로 nativescript/core를 참조하느냐 tns-core-modules/file-system을 사용하느냐 같은 문제다.

프로젝트 폴더에 있는 package.json에 @nativescript/core”:”~8.3.0″ 과 같이 설치되어 있는 경우에는 @nativescript/background-http로 설치하고 버전도 6.0.0 이상을 설치해야 한다.

3. FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingInt…

역시 sdk와의 호환성 문제로 인한 보안 문제가 발생한 경우이다. background-http의 버전이 낮아서 발생하는 문제로 foreground로 해야 한다든지, Notification을 설정해야 한다든지 하는거 모두 해결이 안된다.

버전호환성 때문에 AndroindManifest.xml을 손대보고 했는데 모두 해결되지 않았다. 그냥 마음 편히 버전을 맞추면 해결이 된다. 버전이 맞는데도 계속 발생하면 프로젝트 폴더에 있는 package.json 파일에 background-http가 두개 있지 않은지 확인을 해 보고 버전이 맞는 한개만 남겨두고 삭제한 다음 ns clean, 실행의 순서로 진행한다.

  "dependencies": {
    "@nativescript/background-http": "^6.0.0",
    "@nativescript/camera": "^5.0.13",
    "@nativescript/core": "~8.3.0",
    "@nativescript/imagepicker": "^1.0.7",
    "@nativescript/theme": "~3.0.2",
    "nativescript-background-http": "^4.1.2",  <= 요놈을 삭제 해 버린다.
    "nativescript-camera": "^4.5.0",
    "nativescript-vue": "~2.9.0"
  },

package.json을 수정한 다음에는 저장 후 반드시 ns clean을 하고 가상 머신을 리부팅하거나 데이터를 초기화 해주거나 또는 연결된 개발 기계의 앱을 삭제 후 다시 실행해야 한다.

어떤 경우에는 동일한 작업을 3번 정도 반복했는데 기계에 앱이 그대로 있어서 문제가 되었던거 같았다. 이 경우 기계의 앱을 삭제하고 다시 실행하니 정상으로 돌아왔다.

3. You have to set namespace to your app package name (context.packageName) in your Application

package name을 갑자기 찾을 수 없다고 정의하라고 한다. 이미 package.json이나 jsconfig.json 등에 모두 정의되어 있으나 계속 동일한 에러를 발생시킨다.

이 경우는 Application.android.context가 null이거나 앱의 프로세스 컨텍스트가 아닌 초기화 안된 Dummy같은 컨텍스트라서 packageName이 null인 경우다.

background-http는 import 한 후 바로 init() 명령으로 초기화 해 주어야 하는데 이를 안한 경우다. 초기화도 import 한 후 바로 해 주는게 좋고 다른 function내에서 하는 경우 초기화가 안될 수 있다. 그 이유는 range의 문제로 application 차원의 초기화가 아닌 stack 내에서 또는 subclass 내에서의 초기화라서 application의 컨텍스트 정보를 못가져 온 것이다.

<script>
import { init } from '@nativescript/background-http';

init();

다른데서 하지 말고 import 후 바로 초기화 한다.

Nativescript-vue Build에러가 나는 경우 -(1)

Nativescript-vue Build 에러가 나는 경우는 매우 다양한데 camera 모듈을 추가할 때 어떤걸 해야 할지 몰라 이것 저것 막 추가하다보니 library가 충돌을 일으켰다. Camera 모듈을 추가했는데

WARNING in ../node_modules/nativescript-camera/camera.android.js 20:24-63
Module not found: Error: Can't resolve 'tns-core-modules/utils/types' in 'C:\Project\Vue\node_modules\nativescript-camera'

...

WARNING in ../node_modules/nativescript-camera/camera.android.js 64:34-73
Module not found: Error: Can't resolve 'tns-core-modules/application' in 'C:\Project\Vue\node_modules\nativescript-camera'

와 같은 에러가 5개가 동시에 떴다. 필요 없는 모듈을 지우려고 npm uninstall 명령을 해 봐도 소용이 없고 plugin을 어떻게 하나씩 지우는지 알수도 없어서 인터넷을 여기 저기 뒤져서 찾은 방법은

1. ns clean으로 정리

먼저 프로젝트 폴더에서 ns clean 으로 nativescript의 plugin을 일단 모두 정리한다.

C:\project\vue\myFarm> ns clean
- Cleaning project...
√ Cleaned directory hooks
√ Cleaned directory platforms
√ Cleaned directory node_modules
√ Cleaned file package-lock.json
√ Project successfully cleaned.

C:\project\vue\myFarm> npm list
myFarm@1.0.0 C:\Project\Vue\myFarm
+-- UNMET DEPENDENCY @nativescript/android@8.3.1
+-- UNMET DEPENDENCY @nativescript/core@~8.3.0
+-- UNMET DEPENDENCY @nativescript/preview-cli@1.0.1
+-- UNMET DEPENDENCY @nativescript/theme@~3.0.2
+-- UNMET DEPENDENCY @nativescript/webpack@~5.0.6
+-- UNMET DEPENDENCY nativescript-vue-template-compiler@~2.9.0
`-- UNMET DEPENDENCY nativescript-vue@~2.9.0

npm ERR! code ELSPROBLEMS
npm ERR! missing: @nativescript/android@8.3.1, required by myFarm@1.0.0
npm ERR! missing: @nativescript/core@~8.3.0, required by myFarm@1.0.0
npm ERR! missing: @nativescript/preview-cli@1.0.1, required by myFarm@1.0.0
npm ERR! missing: @nativescript/theme@~3.0.2, required by myFarm@1.0.0
npm ERR! missing: @nativescript/webpack@~5.0.6, required by myFarm@1.0.0
npm ERR! missing: nativescript-vue-template-compiler@~2.9.0, required by myFarm@1.0.0
npm ERR! missing: nativescript-vue@~2.9.0, required by myFarm@1.0.0

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\Admin\AppData\Local\npm-cache\_logs\2022-10-03T04_37_37_063Z-debug-0.log

2. package.json 수정

이 상태에서 build를 하면 다시 재설치되어 버리므로 프로젝트의 package.json 파일을 수정한다.

파일을 열어보면 dependencies 항목에 추가 설치된 plugin 들이 포함되어 있다. 이 중 필요없는 library/plugin을 삭제하고 저장한다.

[ package.json 파일 ]
{
  "name": "myFarm",
  "main": "app/app.js",
  "version": "1.0.0",
  "private": true,
  "dependencies": {
    "@nativescript/camera": "^5.0.13",
    "@nativescript/core": "~8.3.0",
    "@nativescript/theme": "~3.0.2",
    "nativescript-camera": "^4.5.0",
    "nativescript-vue": "~2.9.0"
  },
  "devDependencies": {
    "@nativescript/android": "8.3.1",
    "@nativescript/preview-cli": "1.0.1",
    "@nativescript/webpack": "~5.0.6",
    "nativescript-vue-template-compiler": "~2.9.0"
  }
}

3. build

그 다음 다시 필요한 plugin을 설치하거나 build 또는 android를 실행하면 필요한 라이브러리가 설치된다.

C:\project\vue\myFarm> ns run android

Nativescript-vue Camera 추가

Camera를 사용하기 위해 프로젝트 폴더에서 @nativescript/camera를 추가

C:\project\vue> cd myFarm  // <=== 폴더구조가 C:\project\vue인 경우
C:\project\vue\myFarm> ns  plugin  add  @nativescript/camera

npm 명령으로 nativescript-camera만 추가하고 buil를 했더니 build 에러도 발생하고 Android emulator에 저장할 공간이 없다는 에러도 발생한다. Android 핸드폰(삼성 갤럭시나 구글 Pixel 같은)을 연결해서 개발하거나 Android Studio의 More Action > Virtual Device Manager에서 가상머신의 오른쪽 끝 메뉴를 눌러 Wipe Data를 실행시킨 다음 다시 테스트 한다.

Wipe Data 후에 다시 ns run android를 실행하면 기계의 저장공간이 부족하다는 메시지가 안나온다. 만약 계속 같은 공간 부족 메시지가 나온다면 설정으로 들어가서 저장공간을 늘려줘야 한다.

설치된 plugin을 보면 다음과 같다.

C:\project\vue\myFarm> npm  list

myFarm@1.0.0 C:\Project\Vue\myFarm
+-- @nativescript/android@8.3.1
+-- @nativescript/camera@5.0.13
+-- @nativescript/core@8.3.5
+-- @nativescript/preview-cli@1.0.1
+-- @nativescript/theme@3.0.2
+-- @nativescript/webpack@5.0.8
+-- nativescript-camera@4.5.0
+-- nativescript-vue-template-compiler@2.9.3
`-- nativescript-vue@2.9.3

@nativescript/camera를 import하고 Camera 사용 모듈을 추가

<template>
...
      <StackLayout>
          <Image :src="img" width="100%" />
      </StackLayout>
...
</template>
import * as camera from '@nativescript/camera';
...
export default {
    data() {
        return {
            img:''
        }
    },
    methods:{
        takePicture() {
            camera.requestCameraPermissions()
                .then(() => {
                    camera.takePicture({ width: 300, height: 300, keepAspectRatio: true, saveToGallery: false })
                    .then(imageAsset => {
                        this.img = imageAsset;
                    })
                    .catch(e => {
                        console.log('error:', e);
                    });
                })
                .catch(e => {
                    console.log('Error requesting permission');
                });
            }
        }

camera.takePicture에 의해 사진이 찍히면 this.img 가 update되고, 자동으로 Image의 src가 update된다.

Nativescript-vue Onload event와 Scrollbar event

처음 화면이 로딩되었을때 Default로 실행하도록 하는 경우 onload 이벤트 핸들러를 사용.

<Page @loaded="read">    // <======= @onload 이벤트 핸들러를 이용하여 페이지 시작시 기본 실행
<ActionBar title="Main List">
<StackLayout>
<Image class="logo" src="~/assets/images/logo.png" /><Label :text="scrollText" />
</StackLayout>
</ActionBar>

<ScrollView @scroll="read">  // <====== @scroll 이벤트 핸드러를 이용하여 페지이 스크롤시 실행
<StackLayout>
<Post v-for="(item, index) in posts"
:key="index"
:Image="item.Image"
:Favor="item.Favor"
/>
</StackLayout>
</ScrollView>
</Page>

이 경우 페이지를 조금만 움직여도 바로 스크롤 이벤트가 발생하므로 이벤트 처리시에 이를 체크하도록 코드 추가

methods: {
    read(args) {
        if( ... &&  args.object.verticalOffset != undefined && args.object.scrollableHeight != undefined) {
            if ( args.object.verticalOffset < args.object.scrollableHeight * 0.99 ) {
                return true;
            }
        }

스크롤 이벤트 발생시 넘어온 args 파라미터는 다음이 속성들을 가지고 체크할 수 있음.

//args.object.getMeasuredHeight() : 화면상 높이
//args.object.effectiveHeight :
//args.object.height : css 상 높이. 보통 auto
//args.object.scrollableHeight : scroll bar 로 나타낼 수 있는 최대 높이