Unsupported Modules Detected: Compilation is not supported for following modules: . Unfortunately you can't have non-Gradle Java modules and Android-Gradle modules in one project.

 

로컬로 백업해둔 프로젝트를 Android Studio에  import 하는 과정에서 위와 같은 애러 메시지가 뜨면서

컴파일이 되지 않거나, 프로잭트가 소스가 중복으로 생성되는 현상이 발생

실행하고 있는 안드로이드 스튜디오를 종료 -> 해당 프로젝트가 있는 위치로 이동(탐색기 또는 파인더) ->

.idea 폴더를 삭제 -> 모든 .iml 파일들을 삭제

 

이렇게 하고 다시 실행해보니 잘 작동하게됨

 

새노트북을 구입하여 윈도우 사용자 명을 영어로 설정하는걸 깜빡하고, 한글로 설정해버려

Android studio 설치 경로 아스키코드 오류가 발생

Your project file contains non-ASCII characters. 

SDK설치 경로를 d:\android\sdk 로 변경 하여 설치를 완료 할 수 있었는데

에뮬레이터 실행 과정중 애러발생

emulator: panic: broken avd system path. check your android_sdk_root value [d:\android\sdk]

몇시간 구글링 검색하면 대부분 아래 변수를 수정하라고 하지만 해결이안됨

환경변수

변수 이름 : ANDROID_HOME 

변수 값 : D:\Android\Sdk

변수 이름 : ANDROID_ SDK_ROOT 

변수 값 : D:\Android\Sdk

그러다 추가로 아래 환경변수를 추가하니 해결완료

변수 이름 : ANDROID_AVD_HOME 

변수 값 : D:\Android\Sdk

android ACTION_CALL 전화바로 걸기 구현

 

 

 

 

전화걸기 기능을 추가하려면 manifest에 권한을 추가해야한다.

<uses-permission android:name="android.permission.CALL_PHONE"/>

 

btn_call.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:01012345678"));
startActivity(callIntent);
}
});

이대로 작성하면 startActivity에서 에러가 발생한다. 여기에 추가로 예외조건을 추가해주면 완성이 된다.

 

btn_call.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:01012345678"));

try {
startActivity(callIntent);

} catch (Exception e) {
e.printStackTrace();
}

}
});

WebView WebView1 = (WebView) findViewById(R.id.webView1);

//Only hide the scrollbar, not disables the scrolling:
WebView1.setVerticalScrollBarEnabled(false);
WebView1.setHorizontalScrollBarEnabled(false);

//Only disabled the horizontal scrolling:
WebView1.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);

//To disabled the horizontal and vertical scrolling:
webview.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return (event.getAction() == MotionEvent.ACTION_MOVE);
}
});

 

Android Chat Bubble

In this Android tutorial, we will see about how to create an Android (bubble) layout for a chat application. We will use Android ListView with adapter to create the Android chat bubble layout.

Chat bubbles are background image that expands horizontally and vertically as required based on the message posted.

Android-Chat-Bubble

Nine-patch Image

In creating Android chat bubbles, nine-patch image plays a crucial role. Nine-patch image is a bitmap which stretches to fit the content posted in the View where it is applied as a background.

A NinePatch drawable is a standard PNG image that includes an extra 1-pixel-wide border. It must be saved with the extension .9.png, and saved into the res/drawable/ directory of your project. The border is used to define the stretchable and static areas of the image. You indicate a stretchable section by drawing one (or more) 1-pixel-wide black line(s) in the left and top part of the border (the other border pixels should be fully transparent or white). You can have as many stretchable sections as you want: their relative size stays the same, so the largest sections always remain the largest.

We can use the draw9patch tool provided with the Android-sdk to create a nine-patch image. There are lots of free online tools available to generate these images. Of course, we can use Photoshop and create ourselves.

bubble_a.9

bubble_b.9

Bubble ListView with Adapter

ListView will be the container to hold the chat conversation. We will customize the underlying Adapter which is responsible for each unit of the data that is displayed in the ListView. We will have a TextView for each of the rows in the list, with a nine-patch image background.

activity_chat_singlemessage.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >

    <LinearLayout
        android:id="@+id/singleMessageContainer"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@+id/singleMessage"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="5dip"
            android:background="@drawable/bubble_b"
            android:paddingLeft="10dip"
            android:text="Hello bubbles!"
            android:textColor="@android:color/primary_text_light" />
    </LinearLayout>

</LinearLayout>

activity_chat.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="80dp">
    </ListView>

    <RelativeLayout
        android:id="@+id/form"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:orientation="vertical" >

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="textMultiLine"
            android:ems="10"
            android:id="@+id/chatText"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_toLeftOf="@+id/buttonSend" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Send"
            android:id="@+id/buttonSend"
            android:layout_alignBottom="@+id/chatText"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true" />
    </RelativeLayout>

</RelativeLayout>

Chat Bubble Activity

We have a main Android Activity that is bind with the ListView coupled with the Adapter. For the sake of this example tutorial, I am changing the bubble background alternately. Those things can go in the business logic of you application.

ChatBubbleActivity.java

package com.javapapers.android.chat;

import android.app.Activity;
import android.content.Intent;
import android.database.DataSetObserver;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnKeyListener;
import android.widget.AbsListView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;

public class ChatBubbleActivity extends Activity {
    private static final String TAG = "ChatActivity";

    private ChatArrayAdapter chatArrayAdapter;
    private ListView listView;
    private EditText chatText;
    private Button buttonSend;

    Intent intent;
    private boolean side = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent i = getIntent();
        setContentView(R.layout.activity_chat);

        buttonSend = (Button) findViewById(R.id.buttonSend);

        listView = (ListView) findViewById(R.id.listView1);

        chatArrayAdapter = new ChatArrayAdapter(getApplicationContext(), R.layout.activity_chat_singlemessage);
        listView.setAdapter(chatArrayAdapter);

        chatText = (EditText) findViewById(R.id.chatText);
        chatText.setOnKeyListener(new OnKeyListener() {
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
                    return sendChatMessage();
                }
                return false;
            }
        });
        buttonSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                sendChatMessage();
            }
        });

        listView.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
        listView.setAdapter(chatArrayAdapter);

        //to scroll the list view to bottom on data change
        chatArrayAdapter.registerDataSetObserver(new DataSetObserver() {
            @Override
            public void onChanged() {
                super.onChanged();
                listView.setSelection(chatArrayAdapter.getCount() - 1);
            }
        });
    }

    private boolean sendChatMessage(){
        chatArrayAdapter.add(new ChatMessage(side, chatText.getText().toString()));
        chatText.setText("");
        side = !side;
        return true;
    }

}

ChatArrayAdapter.java

package com.javapapers.android.chat;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class ChatArrayAdapter extends ArrayAdapter {

	private TextView chatText;
	private List chatMessageList = new ArrayList();
	private LinearLayout singleMessageContainer;

	@Override
	public void add(ChatMessage object) {
		chatMessageList.add(object);
		super.add(object);
	}

	public ChatArrayAdapter(Context context, int textViewResourceId) {
		super(context, textViewResourceId);
	}

	public int getCount() {
		return this.chatMessageList.size();
	}

	public ChatMessage getItem(int index) {
		return this.chatMessageList.get(index);
	}

	public View getView(int position, View convertView, ViewGroup parent) {
		View row = convertView;
		if (row == null) {
			LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			row = inflater.inflate(R.layout.activity_chat_singlemessage, parent, false);
		}
		singleMessageContainer = (LinearLayout) row.findViewById(R.id.singleMessageContainer);
		ChatMessage chatMessageObj = getItem(position);
		chatText = (TextView) row.findViewById(R.id.singleMessage);
		chatText.setText(chatMessageObj.message);
		chatText.setBackgroundResource(chatMessageObj.left ? R.drawable.bubble_a : R.drawable.bubble_b);
		singleMessageContainer.setGravity(chatMessageObj.left ? Gravity.LEFT : Gravity.RIGHT);
		return row;
	}

	public Bitmap decodeToBitmap(byte[] decodedByte) {
		return BitmapFactory.decodeByteArray(decodedByte, 0, decodedByte.length);
	}

}

ChatMessage.java

package com.javapapers.android.chat;

public class ChatMessage {
	public boolean left;
	public String message;

	public ChatMessage(boolean left, String message) {
		super();
		this.left = left;
		this.message = message;
	}
}

Download the Android Studio project Chat Bubble

Thanks to Vijay for asking me to try out Android Studio. It is built on the IntelliJ Idea platform. My first experience with Android Studio is good and it is better than my favorite Eclipse. I am going to stick with Android Studio for all Android projects and tutorials. But Eclipse will continue be my IDE for Java development.

 

출처:http://javapapers.com/android/android-chat-bubble/


나인패치(9patch)를 써보자



ㆍ 개발자들도 필수적으로 알아야되는 나인패치를 사용해보도록 

    하겠습니다.

ㆍ 뭐 설명보다는 써보면서 이해하는게 빠를 것 같으므로 

    바로 시작해보겠습니다.





텍스트 입력이 가능한

버튼에 이미지를

background로

입히는 경우가 있습니다.


뭐 이런식으로 들어가겠죠


그런데

버튼에 들어가는

Text가 고정이 아니라

동적으로

변하는 경우면 어떨까요?


만약 텍스트양이 많아지면?


이런식으로

꼴보기 싫게 변합니다


하지만!!

여기서 나인패치를

적용한다면?

다음과 같은

결과물을 얻을수 있습니다.


텍스트의 길이에 상관없이

깔끔한 버튼이미지를

유지할 수 있습니다.


바로 사용법을

알아보도록 하겠습니다.


기본적으로 나인패치는

[sdk]-[tools]-[draw9patch.bat]

에서 실행시킬 수 있습니다.


하지만 요즘은 고맙게도

웹에서 바로 사용할 수 있습니다.

http://romannurik.github.io/AndroidAssetStudio/nine-patches.html



자 먼저 사용할

이미지를 준비합니다

(.png)


그리고 사이즈는 보통

1글자 들어갔을때의

사이즈로 잡아주시면 됩니다


저는 포토샵을 못쓰므로

파워포인트에서 png파일을

만들었습니다.


위에 버튼이미지도 파포로..ㅎㅎ.


본론으로

넘어가서

사이트에 접속후

Select 버튼을 눌러서

이미지를 가져옵니다


가져오면

이런식으로

나타납니다.

(파포수준 ㅠ)


자 이렇게

나오면 두가지를

설정해보도록

하겠습니다.


처음에는

CONTENT PADDING

입니다


여기서는 말그대로

글자가 들어갈 위치를

잡아줍니다.

패딩값을 잡아주는거죠


요론식으로 좌표값을

보면서 하면

더 정확하게 만들 수 있답니다.


요기도 22 

슉슉


22 4콤보 완료


자 두번째는

STRETCH REGIONS

입니다


여기서는 늘려줄 부분을

설정해줍니다.


아 이부분은

도형이 너무 쉬워서.

음 애매하지만..

저 검정색 십자가부분이

늘어나는 부분입니다.

가로든 세로든 증가할때

저 빨간색부분이 길어지는 겁니다


급하게

다른 도형들 하나 예를 들면


이런식으로 위와 비슷하게

STRETCH REGIONS

를 잡아주게 되면

저 아래로 내려오는 뾰족한

부분은 크기가 안변한답니다

이런 식의 결과를

얻을 수 있죠


만약 범위를

이렇게 잡는다면?

아래쪽 가로는

뾰족한 오른쪽 부분


위쪽 가로는 

일자


왼쪽,오른쪽 세로는

색깔이 섞이고도 

해괴한 모양으로

늘어날 것 같군요.


어느 정도 이해가

가실거라..생각하고 

마무리를 하자면

범위를 다 정하고 나면

압축형태로

다운을 받습니다


압축을 풀고

나면


확장자도 특이한

9.png 파일이 생성됩니다

여기서 .9 지우면 

안됩니다.

.9가 있어야 나인패치

효과가 적용됩니다


이제 복사를 해서

프로젝트 drawable

폴더에 넣어서 쓰시면

완료~

 

출처:http://itpangpang.xyz/169

Activity 생성시에 사용되는 Intent Flag 정리

 

안드로이드 엑티비티에 대해 이해하기 위해 필요한 지식은 3가지 정도가 아닐까 생각합니다. 바로 Activity Lifecycle, Task, Intent 입니다. 모두 어느정도 이해를 하시고 계신 상태라고 생각하고 글을 적어보겠습니다.

인텐트를 이용하여 새로운 엑티비티를 띄우기 위해서는 일반적으로 다음과 같은 방법으로 새로운 엑티비티를 실행하게 됩니다.

 

 

Intent intent = new Intent(this, MyActivity.class);
startActivity(intent);

 

 

위의 코드는 다음과 같은 순서로 실행이 됩니다.

 

1. 새로운 MyActivity 인스턴스가 생성됩니다.
2. 이 인스턴스가 현재 태스크 스택의 최상단에 푸시가 됩니다.
3. 엑티비티가 시작되며(onStart) 포그라운드로 가져옵니다. 

 

하지만 위와 같은 인텐트 생성에 관련된 기본적인 실행 방법을 인텐트 플래그를 사용하여 임의로 조정할 수 있습니다.

 

intent.addFlag(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

 

위와 같은 방법을 통해 특정한 플래그 옵션값을 startActivity(intent)가 수행될때 같이 넘겨줄 수 있습니다. 지금부터 이러한 플래그 옵션값들을 좀더 상세기 적어보도록 하겠습니다.

 

 

FLAG_ACTIVITY_BROUGHT_TO_FRONT

이 플래그는 사용자가 설정하는것이 아닌 시스템에 의해 설정되는 값입니다. 엑티비티의 실행모드가 singleTask이고 이미 엑티비티스택에 존재하고 있는 상태라고 가정을 할 때 다시 그 엑티비티가 호출되고 재활용 되었을 경우 자동으로 설정이 됩니다.

 

 

FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET


사용자 삽입 이미지

 

이 플래그를 사용하면 태스크가 리셋될때 플래그가 사용된 엑티비티부터 최상단의 엑티비티까지 모두를 삭제합니다. 리셋은 FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 플래그에 의해 실행이 되는데 시스템에 의해 홈스크린에서 사용자에 의해 백그라운드에 있던 태스크가 포그라운드로 전환될때에 항상 붙게 됩니다.

 

위의 그림에서 볼 수 있듯이 백그라운드와 포그라운드 전환관계에서 CLEAR_WHEN_TASK_RESET 플래그가 설정된 엑티비티와 이후의 엑티비티 모두가 삭제되는것을 알 수 있습니다. 백그라운드로 넘어갔을때 유지를 안해도 될 일회성 엑티비티들은 해당 플래그를 사용하면 도움이 될것이라 봅니다.

 

 

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

 

이 플래그는 인텐트를 이용하여 새로운 태스크를 생성하거나 존재하고 있는 태스크를 포그라운드로 가져오는 경우가 아닌경우에는 사용하여도 아무런 효과가 없습니다. 적절한 경우라면 태스크를 리셋 합니다. 이때에 태스크의 affinity 설정에 맞추어 리셋이 일어나게 되며 FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET과 같은 플래그 설정에 맞추어진 특정 처리가 일어나게 됩니다.

 

 

FLAG_ACTIVITY_CLEAR_TOP

 


사용자 삽입 이미지

 

만약에 엑티비티스택에 호출하려는 엑티비티의 인스턴스가 이미 존재하고 있을 경우에 새로운 인스턴스를 생성하는 것 대신에 존재하고 있는 엑티비티를 포그라운드로 가져옵니다. 그리고 엑티비티스택의 최상단 엑티비티부터 포그라운드로 가져올 엑티비티까지의 모든 엑티비티를 삭제합니다.

 

예를 들면 현재 ABCDE순서로 엑티비티가 스택에 들어있다고 할때 엑티비티E에서 C를 호출하게 되면 D와 E는 스택에서 삭제되고 ABC만이 남아있게 됩니다. 여기서 AB 역시 남는다는 것을 이해하셔야 합니다.

 

 

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

 

 

엑티비티가 새로운 태스크안에서 실행될때에 일반적으로 타겟 엑티비티는 ‘최근 실행된 엑티비티’ 목록에 표시가 됩니다. (이 목록은 홈버튼을 꾹 누르고 있으면 뜹니다) 이 플래그를 사용하여 실행된 엑티비티는 최근실행된엑티비티 목록에서 나타나지 않습니다.

 

 

FLAG_ACTIVITY_FORWARD_RESULT

 

 

기본적으로 엑티비티A가 엑티비티B를 호출하였다고 할 경우 startActivity(intent) 대신에 startActivityForResult(intent) 메서드를 이용하여 호출을 함으로써 엑티비티B의 결과값을 엑티비티A로 전달할 수 있습니다.

 

엑티비티B에서는 setResult(int resultCode)를 정의한 뒤에 종료를 하게 되며 엑티비티B를 호출하였던 엑티비티A는 콜백메서드인 onActivityResult()를 통해 결과값을 전달받게 됩니다.

 


사용자 삽입 이미지

 

이제 엑티비티B가 또다른 엑티비티C를 호출하였다고 가정해 봅시다. 그리고 이렇게 호출된 엑티비티C에서 엑티비티A까지 전달할 결과값을 정의하였습니다. 이 결과값을 B에서 A로 또다른 코드를 통해서 프로그래머의 코드를 통해서 값을 전달하는 번거로움을 피하기 위해 안드로이드에서는 이 인텐트 플래그값을 제공합니다.

 

위에 나와있는 그림의 예를 통해 보면 엑티비티B가 엑티비티C를 호출하기위해 단순히 startActivity()를 이용하는 것을 알 수 있습니다. 그리고 지금 설명중인 플래그를 붙이도록 합니다. 이후에 엑티비티C에서는 setResult()를 통해 결과값을 정의를 한후에 finish()를 통해 엑티비티를 종료하도록 합니다.

 

엑티비티B에서는 단순히 마찬가지로 finish()를 통해 엑티비티를 종료하시기만 하면 됩니다. 이후에 startActivityForResult()를 통해 엑티비티B를 호출했던 엑티비티A는 onActivityResult() 콜백 메서드로 결과값을 받아보시면 엑티비티C에서 정의한 값을 받을 수 있다는것을 알 수 있습니다.

 

 

FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY

 

 

이 엑티비티 플래그는 시스템에 의하여 자동으로 설정되는 플래그입니다. 홈스크린화면에서 홈버튼을 롱클릭함으로써 뜨게 되는 “최근실행목록”을 통해 실행되었을 경우 자동으로 설정됩니다.

 

 

FLAG_ACTIVITY_MULTIPLE_TASK

 

이 엑티비티 플래그는 FLAG_ACTIVITY_NEW_TASK와 함께 사용하지 않으면 아무런 효과가 없는 플래그입니다. 두개의 플래그를 동시에 사용할 경우 새로운 태스크는 재활용되지 않고 무조건 새로 생성되며 피호출되는 엑티비티는 이 새로운 태스트의 최상위 엑티비티가 됩니다. (당연히 하나밖에 없을테니-_-a)

 

 

FLAG_ACTIVITY_NEW_TASK

 

 

이 엑티비티 플래그를 사용하여 엑티비티를 호출하게 되면 새로운 태스크를 생성하여 그 태스크안에 엑티비티를 추가하게 됩니다. 단, 기존에 존재하는 태스크들중에 생성하려는 엑티비티와 동일한 affinity를 가지고 있는 태스크가 있다면 그곳으로 새 엑티비티가 들어가게됩니다.

 

하나의 어플리케이션안에서는 모든 엑티비티가 기본 affinity를 가지고 같은 태스크안에서 동작하는것이 기본적(물론 변경이 가능합니다)이지만 FLAG_ACTIVITY_MULTIPLE_TASK 플래그와 함께 사용하지 않을경우 무조건적으로 태스크가 새로 생성되는것은 아님을 주의하셔야 합니다.

 

 

FLAG_ACTIVITY_NO_ANIMATION

 

 

안드로이드 OS가 2.0으로 올라오면서 새로 추가된 엑티비티 플래그입니다. 이 플래그를 사용할 경우 엑티비티가 스크린에 등장할시에 사용될 수 있는 다양한 애니메이션 효과를 사용하지 않습니다.

 

 

FLAG_ACTIVITY_NO_HISTORY

 

 

이 플래그를 사용할 경우 새로 생성되는 엑티비티는 어떤 태스크에도 보존되지 않게 됩니다. 예를 들면 로딩화면과 같이 다시 돌아오는것이 의미가 없는 화면이라면 이 플래그를 사용하여 태스크에 남기지 않고 자동적으로 화면이 넘어감과 동시에 제거할 수 있습니다.

 

 

FLAG_ACTIVITY_NO_USER_ACTION

 

이 플래그가 설정되면 자동적으로 엑티비티가 호출될 경우에 자동 호출되는 onUserLeaveHint()가 실행되는것을 차단합니다. onUserLeaveHint() 콜백 메서드는 어플리케이션 사용중에 전화가 온다거나 하는등의 사용자의 액션없이 엑티비티가 실행/전환되는 경우에 호출되는 메서드입니다.

 

 

FLAG_ACTIVITY_REORDER_TO_FRONT

 


사용자 삽입 이미지

 

 

호출하려던 엑티비티가 이미 엑티비티 스택에 존재하고 있다면 이 플래그를 사용하여 스택에 존재하는 엑티비티를 최상위로 끌어올려줍니다. 결과적으로 엑티비티 스택의 순서가 재정렬되는 효과를 가집니다. 위의 예를 볼 경우에 엑티비티E가 C를 호출하게 됨으로써 엑티비티C가 최상단으로 이동하는 결과를 확인하실 수 있습니다.

 

 

FLAG_ACTIVITY_SINGLE_TOP

 

 

이 플래그는 말그대로 하나의 탑(?)을 의미하는 설정입니다. 엑티비티를 호출할 경우 호출된 엑티비티가 현재 태스크의 최상단에 존재하고 있었다면 새로운 인스턴스를 생성하지 않습니다. 예를 들어 ABC가 엑티비티 스택에 존재하는 상태에서 C를 호출하였다면 여전히 ABC가 존재하게 됩니다.

 

출처:http://theeye.pe.kr/archives/1298

스피너선택에 따른 엑티비티 전환

 

public class PaymentActivity extends AppCompatActivity {

Button button;
ArrayList arrayList;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_payment);


arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");


final String[] select_item = {""};



Spinner spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>
(this, android.R.layout.simple_spinner_dropdown_item, arrayList);
spinner.setAdapter(adapter);

Button button = (Button) findViewById(R.id.button);



spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
select_item[0] = String.valueOf(arrayList.get(arg2));
}

@Override
public void onNothingSelected(AdapterView<?> arg0) {

}
});



button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (select_item[0].equals("1")) {
Intent intent = new Intent(PaymentActivity.this, Activity1.class);
startActivity(intent);
finish();

} else if (select_item[0].equals("2")) {
Intent intent = new Intent(PaymentActivity.this, Activity2.class);
startActivity(intent);
finish();
}
}
});


}


}

안드로이드에서 html 문서 파싱을 하기 위해 검색을 해보았다. 


RSS를 지원하는 사이트의 파싱은 Xmlpullparser를 이용하는 것이 가장 효율적이라고 한다.

RSS를 지원하지 않는 사이트의 파싱은 DOM이나 Jericho를 사용할 수 있다.


===========================================================================================

첫번째 걸린 블로그이다.  http://blog-kr.specialguy.net/130


자바 html 파서 jericho의 안드로이드용이 다음 주소에 있다.

 jericho-android.jar 를 다운로드 하여 임포트 하여 쓰면 된다고 한다.

http://blog.naver.com/zeanz?Redirect=Log&logNo=110092582999


===========================================================================================


이클립스에서 jericho.jar를 임포트 하는 방법이다. 

출처는 http://dodo4989.tistory.com/106


먼저 Project에 라이브러리를 import시킨다.

즉, Project -> import -> General -> File System -> jar파일등록하면 

Project에 해당 Library가 추가된다.

 

다음으로는 해당 Library를 Project에서 사용할 수 있도록 설정을 해주어야 한다.

Project선택 후

Properties(Alt + Enter) -> Java Build Path -> Libraries Tab -> Add JARs -> JAR파일 선택

 


또는 import 시키지 않고 외부에서 Library를 가져올 수 도 있다.

 

Project선택 후

Properties(Alt + Enter) -> Java Build Path -> Libraries Tab -> Add External JARs -> JAR파일 선택

 

 

 

*. 추가 확인 사항

Jericho HTML Parser를 설치한 후에 java 소스 상에서 아래와 같이 사용할 경우.

Source source = null;

source = new Source(new URL(sourceUrlString));

Source Import시 두가지 중 import net.htmlparser.jericho.Source; 를 설정해 주어야 한다


 

 

===========================================================================================

사용 예제 하나 

http://blog.naver.com/mysk4521?Redirect=Log&logNo=40093081572


===========================================================================================

다른 블로그의 포스트 내용 중 일부다. http://blog.naver.com/freemagick/100138927843

1. jericho 파서를 다운받아 넷빈즈 프로젝트폴더의 libs안에 넣어준다.

2. manifest에서 

<uses-permission android:name="android.permission.INTERNET" /> 를 넣어준다. </application>다음에 넣어주도록한다.(이걸 안해주면 실행시 source객체를 이용할때 에러가뜨며 종료됨)


===========================================================================================

또 다른 사용 예를 살펴본다. 코드 출처는 http://ckritbuddy.tistory.com/42


이 예제는 주어진 url의 html을 읽어온 후 구문분석을 하고 그 중에서 text만 추출하여

텍스트뷰에 출력하는 작업을 수행한다.


// Jericho.java

package aa.bb.zz.Jericho;


import java.net.URL;

import net.htmlparser.jericho.Source;


import android.app.Activity;

import android.os.Bubdle;

import android.widget.TextView;


public class Jericho extends Activity {

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);


String yourUrl = "http://code.google.com/intl/ko/android/";


TextView tv = (TextView)findViewById(R.id.mainTextView);

tv.setText(getHtmltoText(yourUrl));

}


public String getHtmltoText(String sourceUrlString) {

Source source = null;

String content = null;


try {

//url에서 html 소스를 읽어온다.

source=new Source(new URL(sourceUrlString));

// 한글사용을 위해서는 윗 줄의 코드를 아래처럼 수정

// URL sUrl = new URL(sourceUrlString);

// InputStream is = sUrl.openStream();

// Source source= new Source(new InputStreamReader(is,"euc-kr"));

// "euc-kr" 부분은 charset에 맞춰 변경해준다. UTF-8, KSC5601 etc...


// 전체 소스 구문을 분석한다.

source.fullSequentialParse();

// HTML markup에서 text contents만 가져와서 스트링으로 변환한다.

content=source.getTextExtractor().toString();

} catch (Exception e) {

e.printStackTrace();

}

return content;

}

}



===========================================================================================

사용 예 하나더 , 택배조회 하는 예제 // 코드 출처는 http://webfine.tistory.com/4

CJ 택배 운송장 조회사이트를 파싱하여 배송현황만 추출하고 콘솔에 결과를 출력하는 소스이다.

사이트 모양은 위 링크 참조


List를 사용하는 부분들은 자료값을 가지고 와서 콘솔창에 찍어주기 위해 적은 부분으로, 마지막을 DB부분에 넣거나 View 페이지로 자료 값을 넘겨주어서 노출 시킬 수도 있습니다.

여기서 가장 중요한 부분은 getAllElements(HTMLElementName.태그이름.get(순서) 부분으로 실질적으로 해당 태그안의 값을 가져오는 부분입니다. 해당이름으로 된 태그의 자식태그들을 모두 가져 오는 것이 getAllElements() 메소드입니다.

해당 페이지를 소스 보기 하신 후 자식태그를 제외한 부모태그들만 순서를 계산하여서 가지고 오는 것이지요. 순서는 0번 부터 입니다.

그 데이터를 가져 온 부분에서 계속 하위로 검색을 하다보면 마지막에 자신이 원하는 값을 가진 HTML 부분은 파싱할 수 있을 것입니다.

단점은 해당 페이지의 디자인이 변경된다면 다시 소스를 작업해야 한다는 것이지만, 실제 DB에 접속이 불가능하지만 웹사이트에서 노출 되는 부분들이 있다면 이 방식으로 데이터를 가져올 수 있습니다.




import java.io.IOException;

import java.net.MalformedURLException;

import java.net.URL;

import java.util.ArrayList;

import java.util.Iterator;

import java.util.List;

 

import net.htmlparser.jericho.Element;

import net.htmlparser.jericho.HTMLElementName;

import net.htmlparser.jericho.Source;

 

public class HtmlTableTagParse {

    public static void main(String[] args) 

      throws MalformedURLException, IOException {




        //송장 번호를 받는다.

        String num = "602411606750";

         

        //송장 번호와 cj택배에 배송추적 관련 주소와 연결 시킨다.

          String url ="http://www.cjgls.co.kr/kor/delivery/service/

 


            searchView_1.asp?slipnom=" + num;

         

        //해당 URL 페이지를 가져온다.

        Source source = new Source(new URL(url));

         

        //메소드 찾기를 위해 시작부터 끝까지 태그들만 parse 한다 (?)

        source.fullSequentialParse();

         

        //해당 데이터가 있는 부분을 찾는 부분.

        Element div = source.getAllElements(HTMLElementName.DIV).get(2);

         

        Element table = div.getAllElements(HTMLElementName.TABLE).get(1);

         

        List trList = table.getAllElements(HTMLElementName.TR);

         

        Iterator trIter = trList.iterator();

         

        trIter.next();

         

        while(trIter.hasNext()){

            Element tr = (Element) trIter.next();

 

            List dataList = tr.getAllElements(HTMLElementName.TD);

             

            Iterator dataIter = dataList.iterator();

             

            int chk = 0;

             

            List resultList = new ArrayList();

             

            //원하는 결과 값이 들어가는 부분.

            List rowList = new ArrayList();

             

            while(dataIter.hasNext()){

                Element data = (Element) dataIter.next();

                String value = 

                          data.getContent().getTextExtractor().toString();

                rowList.add(chk,value);

                 

                chk++;

                 

                if(chk == 5){

                    resultList.add(rowList);

                    chk = 0;

                }

            }

             

            //콘솔 창에서 확인 하기 위한 부분.

            Iterator resultIter = resultList.iterator();

             

            while(resultIter.hasNext()){

                List list = (ArrayList)resultIter.next();

                 

                System.out.println((String)list.get(0) + list.get(1) +

                                list.get(2) + list.get(3) + list.get(4));

            }

        }

         

    }


 

안드로이드/Android Custom Dialog 만들기 

TestCustomDialogActivity.Java 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package arabiannight.tistory.com;
 
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import arabiannight.tistory.com.popup.CustomDialog;
 
public class TestCustomDialogActivity extends Activity {
 
    private CustomDialog mCustomDialog;
     
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
 
    public void onClickView(View v){
        switch (v.getId()) {
        case R.id.bt_main:
            mCustomDialog = new CustomDialog(this,
                    "8월의 크리스마스!!",
                    "영화보러가자~!!!",
                    leftClickListener,
                    rightClickListener);
            mCustomDialog.show();
            break;
        }
    }
 
    private View.OnClickListener leftClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(getApplicationContext(), "왼쪽버튼 Click!!",
                    Toast.LENGTH_SHORT).show();
        }
    };
 
    private View.OnClickListener rightClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(getApplicationContext(), "오른쪽버튼 Click!!",
                    Toast.LENGTH_SHORT).show();
        }
    };
}



CustomDialog.Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package arabiannight.tistory.com.popup;
 
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import arabiannight.tistory.com.R;
 
public class CustomDialog extends Dialog{
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
         
        WindowManager.LayoutParams lpWindow = new WindowManager.LayoutParams();   
        lpWindow.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND;
        lpWindow.dimAmount = 0.8f;
        getWindow().setAttributes(lpWindow);
         
        setContentView(R.layout.custom_dialog);
         
        setLayout();
        setTitle(mTitle);
        setContent(mContent);
        setClickListener(mLeftClickListener , mRightClickListener);
    }
     
    public CustomDialog(Context context) {
        // Dialog 배경을 투명 처리 해준다.
        super(context , android.R.style.Theme_Translucent_NoTitleBar);
    }
     
    public CustomDialog(Context context , String title ,
            View.OnClickListener singleListener) {
        super(context , android.R.style.Theme_Translucent_NoTitleBar);
        this.mTitle = title;
        this.mLeftClickListener = singleListener;
    }
     
    public CustomDialog(Context context , String title , String content ,
            View.OnClickListener leftListener , View.OnClickListener rightListener) {
        super(context , android.R.style.Theme_Translucent_NoTitleBar);
        this.mTitle = title;
        this.mContent = content;
        this.mLeftClickListener = leftListener;
        this.mRightClickListener = rightListener;
    }
     
    private void setTitle(String title){
        mTitleView.setText(title);
    }
     
    private void setContent(String content){
        mContentView.setText(content);
    }
     
    private void setClickListener(View.OnClickListener left , View.OnClickListener right){
        if(left!=null && right!=null){
            mLeftButton.setOnClickListener(left);
            mRightButton.setOnClickListener(right);
        }else if(left!=null && right==null){
            mLeftButton.setOnClickListener(left);
        }else {
             
        }
    }
     
    private TextView mTitleView;
    private TextView mContentView;
    private Button mLeftButton;
    private Button mRightButton;
    private String mTitle;
    private String mContent;
     
    private View.OnClickListener mLeftClickListener;
    private View.OnClickListener mRightClickListener;
     
    /*
     * Layout
     */
    private void setLayout(){
        mTitleView = (TextView) findViewById(R.id.tv_title);
        mContentView = (TextView) findViewById(R.id.tv_content);
        mLeftButton = (Button) findViewById(R.id.bt_left);
        mRightButton = (Button) findViewById(R.id.bt_right);
    }
     

+ Recent posts