안드로이드 폰마다 해상도가 달라서 그리드뷰에서 이미지가 다르게 나오는군요~

폰의 화면 해상도에 따라 각 셀의 이미지 폭을 계산하는 방법입니다.

	<GridView
	    xmlns:android="http://schemas.android.com/apk/res/android"
	    android:id="@+id/gridview"
	    android:layout_width="fill_parent"
	    android:layout_height="0dip"
	    android:layout_weight="1"
	    android:columnWidth="100dp"
	    android:numColumns="3"
	    android:verticalSpacing="10dp"
	    android:horizontalSpacing="10dp"
	    android:stretchMode="columnWidth"
	    android:gravity="center"
	    />

위의 android:numColumns 숫자로 Width 를 나누면 됩니다.

그리고 나누기 전에 horizontalSpacing 이 있으므로 그 값을 미리 빼서 나누어야 합니다.

mGridView = (GridView)findViewById(R.id.gridview);
mCellSize = (this.getResources().getDisplayMetrics().widthPixels - mGridView.getRequestedHorizontalSpacing() ) / 3;

여기서 구한 mCellSize 를 mGridView.setAdapter 함수 호출시 값을 전달합니다.
mGridView.setAdapter(new ImageAdapter(getBaseContext(), thumbPath, mCellSize));

public class ImageAdapter extends BaseAdapter {
	private Context mContext;
	private int mCellSize = 0;

	public ImageAdapter(Context c, String[] thumbPath, int cellSize) {
		mContext = c;
		mCellSize = cellSize;
	}

	public Object getItem(int position) {
		return null;
	}
	
	public long getItemId(int position) {
		return 0;
	}
	
	public View getView(int position, View convertView, ViewGroup parent) {
		ImageView imageView;
		if(convertView == null) {
			imageView = new ImageView(mContext);
			imageView.setLayoutParams(new GridView.LayoutParams(mCellSize, mCellSize));
			imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
			imageView.setPadding(1, 1, 1, 1);
		}
		else {
			imageView = (ImageView)convertView;
		}
		
		imageView.setImageURI(Uri.parse(thumbPath[position]));
		
		return imageView;
	}
}

GridView에 자동으로 표시하는 옵션이 생기면 좋을텐데 아쉽군요~

 

블로그 이미지

iVPS 영은파더♥

가상서버호스팅 VPS 리눅스 서버관리 윈도우 IT

댓글을 달아 주세요

웹뷰에서 http:// 링크를 열때 "net::ERR_CLEARTEXT_NOT_PERMITTED" 오류 메시지가 나오는 폰이 있네요~

폰 마다 다른데 AndroidOne 이라서 그런지 https:// 페이지는 이상없이 잘 열리는데 http:// 보안서버가 아닌 페이지는 안되는군요~

해결 방법은 AndroidManifest.xml 에서 application 태그안에

android:usesCleartextTraffic="true"

위 코드를 넣어주면 해결이 됩니다.

 

블로그 이미지

iVPS 영은파더♥

가상서버호스팅 VPS 리눅스 서버관리 윈도우 IT

댓글을 달아 주세요

웹 페이지에서 자신이 만든 특정앱을 호출 실행하는 방법니다.

1. AndroidManifest.xml 파일에서 웹링크를 눌렀을때 실행될 액티비티를 정의합니다.

<activity
    android:name=".MyViewActivity"
    android:label="@string/app_name"
    android:screenOrientation="portrait"
    android:theme="@android:style/Theme.NoTitleBar">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="스키마" android:host="호스트" />
    </intent-filter>
</activity>

  스키마, 호스트 <= 이 부분을 정의합니다.

 

2. MyViewActivity onCreate 함수에 아래 코드를 넣어서 웹에서 호출될 때 값을 파싱합니다.

Uri uriData = getIntent().getData();
if(uriData != null) {
    String param1 = uriData.getQueryParameter("param1");
    Log.e( "MyViewActivity", "Param1 : " + param1);
}

 

3. 웹 페이지에 앱을 실행할 코드를 작성합니다.

<a href="intent://호스트?param1=data1#Intent;
scheme=스키마;
action=android.intent.action.VIEW;
category=android.intent.category.BROWSABLE;
package=com.example.www;
end">
앱호출
</a>

  호스트, 파라메터, 스키마, package 를 자신에게 맞게 수정합니다.

앱을 미리 컴파일해서 실행을 한번 해준 다음에 웹 브라우저에서 위 링크를 눌러서 확인하면 됩니다.

 

 

블로그 이미지

iVPS 영은파더♥

가상서버호스팅 VPS 리눅스 서버관리 윈도우 IT

댓글을 달아 주세요

안드로이드 구글 애드몹 광고 다는 예제 코드를 찾다가 보니 구글에서 가이드 해주는 샘플이 최고인 듯 하네요~

https://developers.google.com/admob/android/banner?hl=ko

 

배너 광고  |  Android  |  Google Developers

배너 광고는 앱의 레이아웃 안에 표시되는 직사각형 이미지 또는 텍스트 광고입니다. 사용자가 앱과 상호작용하는 동안 화면에 머무르며 특정 시간이 지나면 자동으로 새로고침할 수 있습니다. 모바일 광고를 처음 시작하는 경우 이 형식부터 이용해 보시기 바랍니다. 이 가이드에는 AdMob의 배너 광고를 Android 앱에 통합하는 방법이 나와 있습니다. 코드 스니펫과 지침 외에도 배너 크기 조정에 대한 정보와 추가 리소스에 대한 링크가 포함되어 있습니다. 기본 요

developers.google.com

 

아래는 테스트용 샘플 광고 코드입니다.

배너 광고 ca-app-pub-3940256099942544/6300978111
전면 광고 ca-app-pub-3940256099942544/1033173712
전면 동영상 광고 ca-app-pub-3940256099942544/8691691433
보상형 동영상 광고 ca-app-pub-3940256099942544/5224354917
네이티브 광고 고급형 ca-app-pub-3940256099942544/2247696110
네이티브 동영상 광고 고급형 ca-app-pub-3940256099942544/1044960115

자신이 만든 광고 배너 단위 코드로는 광고가 바로 안나오는 듯 합니다.

 

블로그 이미지

iVPS 영은파더♥

가상서버호스팅 VPS 리눅스 서버관리 윈도우 IT

댓글을 달아 주세요

안드로이드에서 사용가능한 아이콘을 다운로드 받을 수 있는 사이트입니다.

무료인지는 잘 모르겠지만 구글에서 운영하는 사이트로 보여지네요~

https://material.io/tools/icons/?style=baseline

 

Icons - Material Design

Material icons are delightful, beautifully crafted symbols for common actions and items. Download on desktop to use them in your digital products for Android, iOS, and web.

material.io

[안드로이드] 아이콘 다운로드 사이트

위의 아이콘 외에도 엄청 많습니다.

url 링크로 한번 가서 둘러보세요~

png 또는 svg 로 다운로드 받을 수 있더군요~

 

블로그 이미지

iVPS 영은파더♥

가상서버호스팅 VPS 리눅스 서버관리 윈도우 IT

댓글을 달아 주세요

삼성 갤럭시윈에 리눅스를 설치하는데 "Missing parameters: TARGET_PATH" 메시지 이후로 더 이상 설치가 안되는군요~

Missing parameters: TARGET_PATH

Debug 모드를 켜고 로그를 보니 Permission denied 퍼미션 문제로 나오는군요~

인터넷에 검색해서 아래 처럼 설정하고 진행하니 잘 됩니다.

왼쪽 상단에 옵션을 실행해서 설정으로 들어가서 아래의 옵션 값으로 설정을 합니다.

ENV 폴더 : /data/user/0/ru.meefik.linuxdeploy/files

PATH 값 : /system/xbin/

CLI 활성화 체크

ENV 업데이트

이제 다시 설치를 해보세요~

 

블로그 이미지

iVPS 영은파더♥

가상서버호스팅 VPS 리눅스 서버관리 윈도우 IT

댓글을 달아 주세요

LG 옵티머스 GK 스마트폰에 리눅스를 한번 설치해 보았습니다.

Play 스토어에서 Linux Deploy 앱을 설치합니다.

Linux Deploy

생각 보다 많은 분들이 설치를 하였네요~

앱을 실행하면 도움말이 자세하게 나와있습니다.

루팅하는 방법은 http://blog.ivps.kr/711 여기를 참고하세요~

2번의 링크를 눌러서 BusyBox 를 설치합니다.

 

BusyBox

설치하고 실행합니다.

 

설치를 눌러서 진행합니다.

 

루트 권한이 필요하다고 창이 뜨면 ALLOW 를 누릅니다.

 

BusyBox 설치가 완료되었습니다.

이제 다시 Linux Deploy 앱에서 원하는 리눅스 종류를 선택합니다.

저는 CentOS 를 선택했습니다.

 

ssh 에 사용할 계정과 비밀번호를 설정합니다.

 

그리고 SSH 활성화 항목에 체크를 합니다.

 

상단 오른쪽을 터치해서 설치를 진행합니다.

 

루트 권한을 요청하는 팝업이 뜨면 허용을 해줍니다.

 

30분 넘게 기다리면 설치가 완료됩니다.

물론 사용자 환경에 따라 시간은 달라질 수 있습니다.

 

위의 화면 처럼 <<< deploy 가 나오면 왼쪽 하단의 시작 버튼을 눌러서 리눅스 서비스를 시작합니다.

 

Starting extra/ssh ... done 이 나오는 것을 확인합니다.

이제 ssh 접속이 가능한 ssh client 앱을 설치하고 127.0.0.1 22번 포트로 연결합니다.

저 위에서 설정한 계정 정보로 로그인을 합니다.

공유기 와이파이로 연결되어서 그런지 192.168.x.x 로는 접속이 안되네요~

공유기에서 ssh 포트를 포트포워딩하고 외부아이피로 접속을 하니깐 잘 됩니다.

 

블로그 이미지

iVPS 영은파더♥

가상서버호스팅 VPS 리눅스 서버관리 윈도우 IT

댓글을 달아 주세요

Kingo ROOT 앱과 같은 구글 플레이 스토어에 등록되지 않은 앱을 설치하다 보면 "Play 프로텍트에 의해 차단됨" 메시지를 볼 수가 있습니다.

이 화면에서 세부정보를 눌러서 계속 설치(안전하지 않음) 을 눌러서 설치를 하면 됩니다.

혹시 확인을 눌렀다면 앱을 재 설치 시도하더라도 더 이상 설치가 되지 않습니다.

 

이런 경우에는 애플리케이션 관리에서 "Google Play 스토어" 앱의 데이터 삭제를 하고 다시 설치하면 됩니다.

 

블로그 이미지

iVPS 영은파더♥

가상서버호스팅 VPS 리눅스 서버관리 윈도우 IT

댓글을 달아 주세요

집에 굴러다니는 오래된 모델인 갤럭시윈(그리고, 갤럭시S3, LG 옵티머스 GK)에 Linux Deploy 로 리눅스 설치 한번 해 보려고 루팅을 해 보았습니다.

인터넷에 루팅앱을 검색해 보니 TowelRoot 와 KingoRoot 등이 있더군요~

towelroot.com 에서 받은 앱은 설치까지는 성공했지만 제가 가지고 있는 모델로는 루팅까지는 안되네요~

다음으로 시도해본 kingoapp.com 에서 다운로드 받은 앱으로 시도하였습니다.

KingoRoot

www.kingoapp.com 에서 안드로이드용 KingoRoot.apk 를 다운로드합니다.

 

KingoRoot.apk

다운로드 받은 앱을 실행합니다.

 

설치를 하다보면 Play 프로텍트에 의해 차단됨 메시지 창이 뜨는데 세부정보를 눌러서 계속 설치(안전하지 않음)을 누르면 됩니다.

 

Play 프로텍트에 의해 차단됨

그냥 확인 눌렀다면 다음부터는 더 이상 설치가 되지 않습니다.

다시 설치하려면 애플리케이션 관리에서 "Google Play 스토어" 앱의 데이터를 삭제하고 다시 진행하면 됩니다.

Google Play 스토어 데이터 삭제

앱을 설치하였다면 실행합니다.

 

Kingo ROOT

일부 모델은 위 화면에서 One Clink Root 를 실행하면 안드로이드 앱 만으로도 루팅이 됩니다.

"ROOT FAILED" 가 메시지가 나오면서 실패했다면 아래의 PC 버전으로 루팅하는 방법을 이용합니다.

 

아래는 PC와 연결해서 루팅하는 방법입니다.

 

앱을 실행한 상태에서 이제 윈도우용 Kingo Root 프로그램을 다운로드 받아서 설치합니다.

 

미리 폰에서 USB Debugging 을 허용한 상태여야 합니다.

단말기와 PC 를 USB 케이블로 연결하고 프로그램을 실행합니다.

 

조금 지나면 폰에서 자동으로 Kingo Link 앱을 설치 시도가 됩니다.

세부정보를 눌러서 계속 설치를 합니다.

 

연결이 된 상태입니다.

 

ROOT 를 눌르면 됩니다.

 

몇 분이 지나면 루팅이 완료가 됩니다.

 

PC 에서 위 화면이 뜨고 난 뒤에 폰을 보면 아래와 같은 상태인데 One Clink Root 를 실행하면 됩니다.

 

 

ROOT SUCCEEDED 메시지가 뜨면 루팅이 완료된 상태입니다.

 

루팅이 된 상태에서 PC 의 KingoROOT 프로그램을 다시 실행하면 REMOVE ROOT 와 ROOT AGAIN 메뉴가 나타납니다.

 

그리고 폰에서는 아래와 같은 화면이 보입니다.

루팅이 생각 보다 쉽게 되는군요~

 

블로그 이미지

iVPS 영은파더♥

가상서버호스팅 VPS 리눅스 서버관리 윈도우 IT

댓글을 달아 주세요

URL 로 서버에 있는 파일을 AsyncTask 를 활용하여 비동기식으로 다운로드 하는 예제입니다.

 

DownloaderTask task = new DownloaderTask(url, filename); // 파일의 주소와 저장할 파일경로
task.execute(); // 다운로드 시작

task.cancel(true); // 다운로드 취소

package com.example.asyncdownload;

import android.os.AsyncTask;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;

public class DownloaderTask extends AsyncTask<String, String, Boolean> {
	private String TAG = "DownloaderTask";
	public String fileUrl = null;
	public String filePath = null;
	public long fileSize = -1;
	public long downloadSize = 0;
	public Boolean downloadEnd = false;

	public DownloaderTask(String url, String file) {
		this.fileUrl = url;
		this.filePath = file;
	}

	protected Boolean doInBackground(String... params) {
		Log.i( TAG, "doInBackground" );
		Boolean result = false;
		InputStream input = null;
		OutputStream output = null;
		URLConnection connection = null;

		try {
			URL url = new URL( fileUrl );
			connection = url.openConnection();
			connection.connect();

			fileSize = connection.getContentLength();
			Log.i( TAG, "fileLength : " + fileSize+"");
			input = new BufferedInputStream(url.openStream(), 8192);
			File outputFile = new File( filePath );
			Log.i( TAG, "outputFile : " + outputFile+"");
			output = new FileOutputStream(outputFile);

			byte[] buffer = new byte[8192];
			for (int bytesRead; (bytesRead = input.read(buffer)) >= 0; ) {
				if(isCancelled()) {
					Log.i( TAG, "isCancelled : " + isCancelled()+"");
					break;
				}
				downloadSize += bytesRead;
				publishProgress(downloadSize + "");
				output.write(buffer, 0, bytesRead);
			}
			output.flush();
			output.close();
			input.close();
			if(isCancelled()) {
				if(outputFile.exists()) { // 다운로드 취소된 파일은 삭제
					outputFile.delete();
					Log.i( TAG, "outputFile.exists() : " + outputFile.exists()+"");
				}
				downloadEnd = true;
				result = false;
			} else {
				result = true;
			}
		} catch (IOException e) {
			e.printStackTrace();
			result = false;
		}

		return result;
	}

	@Override
	protected void onPreExecute() {
		super.onPreExecute();
		Log.i( TAG, "onPreExecute" );
	}

	@Override
	protected void onPostExecute(Boolean aBoolean) {
		super.onPostExecute(aBoolean);
		if(fileSize == downloadSize) {
			downloadEnd = true;
		}
		Log.i( TAG, "onPostExecute" );
	}

	@Override
	protected void onProgressUpdate(String... values) {
		super.onProgressUpdate(values);
		long v = Long.parseLong(values[0]);
		//Log.i( TAG, "onProgressUpdate : " + v );
	}
}

  onPreExecute 제일 먼저 호출되는 함수
  doInBackground 실제 다운로드하는 루틴
  onProgressUpdate 다운로드 하면서 publishProgress 함수에 값을 넣으면 실행되는 함수
  onPostExecute 다운로드가 끝나면 호출되는 함수

 

프로그래스바는 호출하는 Activity 에서 구현하면 됩니다.

 

블로그 이미지

iVPS 영은파더♥

가상서버호스팅 VPS 리눅스 서버관리 윈도우 IT

댓글을 달아 주세요