activity_main.xml

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/root_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Hello"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="World!"/>

    <LinearLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="#c1cfba"/>

</LinearLayout>

 

MainActivity.kt

 

package kr.co.test

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        button1.setOnClickListener {
            val button1Fragment = Button1Fragment()
            val manager = supportFragmentManager
            val transaction = manager.beginTransaction()

            transaction.replace(R.id.fragment_container, button1Fragment)
            transaction.addToBackStack(null)
            transaction.commit()
        }

        button2.setOnClickListener {
            val button2Fragment = Button2Fragment()
            val manager = supportFragmentManager
            val transaction = manager.beginTransaction()

            transaction.replace(R.id.fragment_container, button2Fragment)
            transaction.addToBackStack(null)
            transaction.commit()
        }
    }
}

 

fragment_button1.xml

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <TextView
        android:id="@+id/button1_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello"
        android:textSize="50sp" />

</LinearLayout>

 

Button1Fragment.kt

 

package kr.co.test

import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.fragment.app.Fragment

class Button1Fragment : Fragment(){

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.fragment_button1, container, false)
        val tv = view.findViewById<TextView>(R.id.button1_text_view)

        tv.setOnClickListener{
            tv.setTextColor(Color.RED)
            Toast.makeText(view.context,"TextView clicked.", Toast.LENGTH_SHORT).show()
        }

        return view
    }
}

 

fragment_button2.xml

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <TextView
        android:id="@+id/button2_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="World!"
        android:textSize="50sp" />

</LinearLayout>

 

Button2Fragment.kt

 

package kr.co.test

import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.fragment.app.Fragment

class Button2Fragment : Fragment(){

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.fragment_button2, container, false)
        val tv = view.findViewById<TextView>(R.id.button2_text_view)

        tv.setOnClickListener{
            tv.setTextColor(Color.GREEN)
            Toast.makeText(view.context,"TextView clicked.", Toast.LENGTH_SHORT).show()
        }

        return view
    }
}

 

 

결과

 

 

참고사이트

https://android--code.blogspot.com/2018/02/android-kotlin-fragment-example.html

 아래 그림과 같이 EditText(TextView)에 이미지를 추가하고 싶을 때가 있다. 

 

 그럴 때 다음과 같이 xml 파일의 EditText 태그에서 drawbleStart(왼쪽에 이미지 추가), drawbleEnd(오른쪽에 이미지 추가) 속성을 추가한 다음 원하는 이미지를 등록함으로써 해결할 수 있다. 또한, drawblePadding 속성을 추가하여 이미지와 텍스트 사이에 거리를 줄 수 있다.

<EditText
android:layout_width="300dp"
android:layout_height="wrap_content"
android:hint="WiFi 선택"
android:inputType="text"
android:drawableStart="@drawable/ic_wifi"
android:drawableEnd="@drawable/ic_next"
android:drawablePadding="10dp"/>

'Android' 카테고리의 다른 글

[Android Kotlin] 음성 녹음  (0) 2019.10.04
[Android Kotlin] MobileFFmpeg 사용법  (0) 2019.09.25

 프로젝트 진행 중 프로그래밍을 통해 통해 무선 랜카드의 모드를 managed 모드에서 AP 모드로 바꿔야하는 일이 생겼다. 그래서 Command Line에서 무선 랜카드의 모드를 AP 모드로 바꾸는 방법을 찾아보았고 다음과 같은 방법으로 해결할 수 있었다.

 

 먼저 WiFi AP 모드를 설정하기 위해서는 먼저 가지고 있는 무선 랜카드가 AP 모드를 지원해야한다. AP 모드 지원 여부를 확인하는 방법은 아래와 같이 Command Line에서 iw list 명령을 실행한 다음 Supported interface modes에서 AP가 있는지 확인하면 된다.

 

※ 참고로 내가 사용하는 무선 랜카드는 ipTime의 A3000U이다.

 

 

 무선 랜카드가 AP 모드를 지원하는 것을 확인하였으면 먼저 hostapd를 설치한다. hostapd는 네트워크 인터페이스 카드를 AP 또는 인증 서버 역활을 할 수 있게하는 데몬이다.

sudo apt install hostapd

 

그리고 /etc/hostapd/hostapd.conf 파일을 아래와 같이 작성한다.

interface=wlx88366cfb576c
driver=nl80211
ssid=Catch Catch
hw_mode=g
channel=1
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=3
wpa_passphrase=1234567890
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

 위의 작성한 부분에서 interface=wlx88366cfb576c 부분은 자신의 무선 랜카드의 인터페이스 이름을 적어줘야 한다. 무선 랜카드의 인터페이스 이름을 확인하는 방법은 아래와 같이 ifconfig 명령어로 확인할 수 있다.

 

 

 그리고 ssid=Catch Catch 부분은 다른 사람들에게 보여줄 ssid를 쓰면되고 wpa_passphrase=1234567890 부분은 내 AP에 접속할 때 필요한 비밀번호로 원하는 비밀번호로 변경하면 된다.

 

 이제 /etc/default/hostapd 파일에서 아래와 같이 DAEMON_CONF="/etc/hostapd/hostapd.conf"를 추가해 hostapd 설정 파일의 위치를 /etc/hostapd/hostapd.conf로 지정해준다.

 

 

 이제 hostapd에서 해야할 작업은 끝났다. 다음으로는 내 AP에 접속하는 사용자들에게 IP를 동적으로 할당해주기 위한 DHCP 서버를 설정해야한다.

 

 먼저 isc-dhcp-server를 설치한다.

sudo apt install isc-dhcp-server

 그리고 /etc/default/isc-dhcp-server 파일을 열어 마지막 줄에 INTERFACES="wlx88366cfb576c"와 같이 DHCP 요청을 처리할 인터페이스를 추가한다.

 

 

 그리고 /etc/dhcp/dhcpd.conf 파일을 열어 아래 보이는 부분들을 주석처리한다.

 

 

 그리고 마지막 줄에 아래 내용을 추가한다. 간단하게 내용을 살펴보면 내 AP에 접속한 기기들에게 10.10.0.2 ~ 10.10.0.16 사이에 있는 IP를 할당해주고 라우터(내 AP) IP는 10.10.0.1이다.

subnet 10.10.0.0 netmask 255.255.255.0 {
        range 10.10.0.2 10.10.0.16;
        option domain-name-servers 8.8.8.8;
        option routers 10.10.0.1;
}

 그리고 /etc/network/interfaces 파일을 열어 아래 부분을 추가해준다. wlx88366cfb576c는 AP가 될 인터페이스 이름을 입력하면 된다.

auto wlx88366cfb576c
iface wlx88366cfb576c inet static
address 10.10.0.1
netmask 255.255.255.0

 이제 아래 명령어로 isc-dhcp-server와 hostapd를 실행시킨다.

sudo service isc-dhcp-server start
sudo service hostapd start

 그리고 재부팅 후 iwconfig로 무선 랜카드의 상태를 보면 Mode가 Master로 변한 것을 확인할 수 있고 다른 장치에서 와이파이 목록을 확인해보면 내가 만든 AP가 보이는 것을 확인할 수 있다. 그리고 연결하면 IP가 10.10.0.2 ~ 10.10.0.16 사이에서 할당받는 것을 확인할 수 있다.

 

※ sudo service hostapd start 명령어 실행 시 Failed to start hostapd.service: Unit hostapd.service is masked. 오류가 발생할 경우 Command Line에서 아래 명령어를 입력한다.

sudo systemctl unmask hostapd
sudo systemctl enable hostapd
sudo systemctl start hostapd

 마지막으로 AP에 접속한 기기들이 인터넷을 할 수 있도록 IP forwarding과 IP masquerading 해줘야한다. 먼저 /etc/sysctl.conf/ 파일을 열어 # net.ipv4.ip_forward=1 이 부분을 찾아 net.ipv4.ip_forward=1로 변경해 IP forwarding을 해준다. 

 

 그리고 iptables-persistent를 설치한 다음

sudo apt install iptables-persistent

 sudo iptables -t nat -A POSTROUTING -s 10.10.0.0/16 -o ens33 -j MASQUERADE 명령어를 입력해 IP masquerading을 해준다. 이때 ens33은 인터넷이 가능한 인터페이스 이름이다. 그리고 sudo netfilter-persistent save 명령어로 추가한 정책을 저장한다.

 

 이제 재부팅 후 다른 디바이스 장치에서 내가 만든 AP에 접속하면 인터넷이 되는 것을 확인할 수 있다.

 

 

참고사이트

 

https://medium.com/@arnab.k/ubuntu-how-to-setup-a-wi-fi-hotspot-access-point-mode-192cbb2eeb90

https://askubuntu.com/questions/119393/how-to-save-rules-of-the-iptables

https://github.com/raspberrypi/documentation/issues/1018

+ Recent posts