반응형

Geocoder를 사용하면 주소로 위경도를, 위경도로 주소를 확인 할 수 있다.


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
public class MainActivity extends AppCompatActivity {
 
    Geocoder geocoder;
 
    EditText editText;
    Button button;
    TextView textView;
 
    EditText editText2;
    EditText editText3;
    Button button2;
    TextView textView2;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        geocoder = new Geocoder(this);
 
        editText = findViewById(R.id.editText);
        textView = findViewById(R.id.textView);
        button = findViewById(R.id.button);
 
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                List<Address> addressList;
                String search = editText.getText().toString();
 
                try {
                    addressList = geocoder.getFromLocationName(search, 10);
                    String[] split = addressList.get(0).toString().split(",");
                    String address = split[0].substring(split[0].indexOf("\""+ 1split[0].length() - 2);
                    String latitude = split[10].substring(split[10].indexOf("="+ 1);  // 위도(수평선)
                    String longitude = split[12].substring(split[12].indexOf("="+ 1); // 경도(수직선)
 
                    String data = "Address: " + address + "\n" + "Latitude: " + latitude + "\n" + "Longitude: " + longitude;
                    textView.setText(data);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
 
        editText2 = findViewById(R.id.editText2);
        editText3 = findViewById(R.id.editText3);
        textView2 = findViewById(R.id.textView2);
        button2 = findViewById(R.id.button2);
 
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                List<Address> addressList;
                double latitude = Double.parseDouble(editText2.getText().toString());
                double longitude = Double.parseDouble(editText3.getText().toString());
 
                try {
                    addressList = geocoder.getFromLocation(latitude, longitude, 10);
                    textView2.setText("Address: " + addressList.get(0).getAddressLine(0));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}




실행 화면


간단한 주소를 입력하고 SEARCH GEOGRAPHIC COORDINATE 버튼을 클릭 하면 정확한 주소와 위경도가 표시 된다.


위경도를 입력하고 SEARCH ADDRESS 버튼을 클릭 하면 주소가 표시된다.


주소로 서현역을 검색 하거나 서현역 위경도로 검색하면 addressList[0]에 입력되는 내용은 아래와 같다. (똑같은 양식으로 입력 된다)


Address[addressLines=[0:"대한민국 경기도 성남시 분당구 서현동 성남대로 지하 601 서현"],feature=서현,admin=경기도,sub-admin=null,locality=성남시,thoroughfare=null,postalCode=463-050,countryCode=KR,countryName=대한민국,hasLatitude=true,latitude=37.384938999999996,hasLongitude=true,longitude=127.12326300000001,phone=null,url=null,extras=null]


반응형
Posted by J-sean
:
반응형

Fedora Linux를 설치하고 간단히 웹서버를 만들 수 있다.

 

2021.08.25 - [Linux] - Linux(Ubuntu) Build Your Own Web Server - 리눅스(우분투)로 웹서버 만들기

 

Fedora 설치 중 Root 암호를 설정 한다. User Creation은 하지 않아도 된다.

 

Root 암호를 입력하고 설치를 완료 한다.

 

설치가 완료되면 재부팅하고 위에서 설정한 암호로 로그인 한다.

 

dnf -y install httpd 를 입력하고 Apache HTTP Server를 설치 한다.

 

 

 

Apache HTTP Server 설치가 완료되면 systemctl status httpd를 입력하고 상태를 확인한다. inactive 상태로 나타난다.

 

systemctl start httpd를 입력해 활성화 시키고 다시 systemctl status httpd를 입력해 확인 한다. active 상태로 나타난다.

 

systemctl enable httpd를 입력해 Apache HTTP Sever가 항상 작동 하도록 한다.

 

firewall-cmd --permanent --add-service=http

firewall-cmd --permanent --add-service=https

firewall-cmd --reload

위 명령어들로 방화벽에 http, https service를 등록한다.

 

ifconfig 명령어로 서버의 주소를 확인 한다. (192.168.11.131)

 

다른 컴퓨터로 서버 주소에 접속할 때 위와 같이 나오면 제대로 설정 된 것이다.

 

 

 

/var/www/html로 이동해서 index.html 파일을 생성 한다.

 

a나 i 키를 눌러 파일을 수정 한다.

 

간단한 html코드를 입력 하고 저장한다.

 

다시 다른 컴퓨터에서 서버에 접속했을 때 위와 같이 나오면 제대로 설정 된 것이다.

 

위와 같이 nmcli를 이용해 고정 IP 주소(192.168.11.200)를 정해 줄 수 있다.

 

※ -ipv4.addresses로 지정하면(앞에 -기호 추가) 원하는 주소를 삭제 할 수 있다고 하는데 처음 지정된 주소는 error가 발생 한다.

새로 추가한 주소는 error 없이 삭제 된다.

 

nmtui를 사용하자.

 

※ 설치: dnf install NetworkManager-tui

 

 

 

php를 설치 한다. 이번엔 -y 옵션을 주지 않았다.

 

y를 입력하고 설치를 진행 한다.

 

/var/www/html/index.php파일을 만든다. 파일명은 원하는대로 지정해도 된다.

 

서버에 설치된 php 정보를 보여주는 코드를 작성 하고 저장 한다.

 

httpd를 재시작 한다.

 

http://192.168.11.200/index.php 에 접속 했을때 위와 같은 화면이 나오면 제대로 설정된 것이다.

 

php-<extension>의 형식으로 필요한 PHP extension을 설치 한다.

 

※ 예를 들어 JSON 데이터를 다룬다면 아래와 같이 php-json을 설치 한다.

dnf install php-json

 

관련 업데이트가 함께 진행 된다.

 

반응형
Posted by J-sean
:
반응형

기기가 Android 5.1 API Level 22(Lollipop) 이하를 실행 하거나 앱의 targetSdkVersion이 22 이하인 경우, 아래와 같이 AndroidManifest.xml 파일에만 SEND_SMS(위험 권한)를 요청하면 문자를 보낼 수 있다.


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


그러므로 아래와 같이 간단히 문자를 보내는 코드는 API Level 23(Marshmallow)이전, API Level 22(Lollipop)까지만 가능 하다.


<AndroidManifest.xml>

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



<MainActivity.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
public class MainActivity extends AppCompatActivity {
 
    EditText editText1;
    EditText editText2;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        editText1 = findViewById(R.id.phoneNumber);
        editText2 = findViewById(R.id.message);
 
        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String phoneNumber = editText1.getText().toString();
                String message = editText2.getText().toString();
 
                try {
                    SmsManager smsManager = SmsManager.getDefault();
                    smsManager.sendTextMessage(phoneNumber, null, message, nullnull);
                    Toast.makeText(getApplicationContext(), "Message sent", Toast.LENGTH_SHORT).show();
                } catch (Exception e) {
                    Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
                    e.printStackTrace();
                }
            }
        });
    }
}



기기가 Android 6.0 API Level 23(Marshmallow) 이상을 실행 하거나 앱의 targetSdkVersion이 23 이상인 경우 앱은 런타임에 사용자로부터 권한을 요청해야 한다. 사용자가 언제든지 권한을 취소할 수 있으므로, 앱이 실행할 때마다 권한을 갖고 있는지 여부를 확인해야 한다.


<AndroidManifest.xml>

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



<MainActivity.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
public class MainActivity extends AppCompatActivity {
 
    private final int MY_PERMISSION_REQUEST_SMS = 1001;
 
    EditText editText1;
    EditText editText2;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.SEND_SMS)) {
                // Android provides a utility method, shouldShowRequestPermissionRationale(), that returns true if the user has previously
                // denied the request, and returns false if a user has denied a permission and selected the Don't ask again option in the
                // permission request dialog, or if a device policy prohibits the permission. If a user keeps trying to use functionality that
                // requires a permission, but keeps denying the permission request, that probably means the user doesn't understand why
                // the app needs the permission to provide that functionality. In a situation like that, it's probably a good idea to show an
                // explanation.
 
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle("info");
                builder.setMessage("This app won't work properly unless you grant SMS permission.");
                builder.setIcon(android.R.drawable.ic_dialog_info);
 
                builder.setNeutralButton("OK"new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ActivityCompat.requestPermissions(MainActivity.thisnew String[] {Manifest.permission.SEND_SMS}, MY_PERMISSION_REQUEST_SMS);
                    }
                });
 
                AlertDialog dialog = builder.create();
                dialog.show();
            } else {
                ActivityCompat.requestPermissions(thisnew String[] {Manifest.permission.SEND_SMS}, MY_PERMISSION_REQUEST_SMS);
            }
        }
 
        editText1 = findViewById(R.id.phoneNumber);
        editText2 = findViewById(R.id.message);
 
        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String phoneNumber = editText1.getText().toString();
                String message = editText2.getText().toString();
 
                try {
                    SmsManager smsManager = SmsManager.getDefault();
                    smsManager.sendTextMessage(phoneNumber, null, message, nullnull);
                    Toast.makeText(getApplicationContext(), "Message sent", Toast.LENGTH_SHORT).show();
                } catch (Exception e) {
                    Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
                    e.printStackTrace();
                }
            }
        });
    }
 
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSION_REQUEST_SMS: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0 && grantResults[0== PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(this,"Permission granted.",Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(this,"Permission denied.",Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
}




 


2018년 11월 1일 이후로 구글 플레이에서는 위 예제와 같이 SMS 및 Call Log 권한을 요청하는 앱을 삭제하고 등록을 막기 시작했다.

Reminder SMS/Call Log Policy Changes


※참고

Permissions overview


반응형
Posted by J-sean
:
반응형

정체를 알 수 없는 비행기들을 쫒아낸 Meverick 일행은 연료가 다 떨어져 가는 것을 확인하고 기지로 돌아 가려 합니다. 하지만 호흡이 가빠지는 등 Cougar의 몸 상태가 좋지 않습니다.


Merlin: Cougar, we're running low on gas, we gotta get out of here.

Merlin: Cougar.


Top Gun



Merlin: We're on vapor, Cougar. Let's do it.

Merlin: Cougar. Come on, Cougar.


vapor는 증기 또는 수증기라는 의미 입니다. 비행 중인 조종사가 We're on vapor라고 말한다면 연료가 거의다 떨어지고 겨우 남아 있는 증기로 비행 중이라는 약간 과장된 뜻이지요. 자동차를 운전하다 기름이 떨어져 갈때는 아래와 같이 말할 수 도 있습니다.


Where's a gas station? My car is running on vapors!


반응형
Posted by J-sean
:
반응형

Cougar와 Merlin, Maverick과 Goose는 비행 도중 정체를 알 수 없는 비행기들이 접근 하고 있다는걸 알게 됩니다.


Maverick: Talk to me, Goose.

Goose: Roger, I got him. Contact, 20 left at 30 miles. Nine-hundred knots closure.


Top Gun



Maverick: Cougar, you hear that?

Cougar: Roger.


knot는 1시간에 1해리의 거리를 나아가는 선박이나 항공기의 속도 단위 입니다. 900 knots closure는 서로의 상대 속도가 900 knots 라는 의미입니다. 예를 들어 한 비행기는 400 knots로, 다른 비행기는 500 knots의 속도로 서로를 향해 날아가고 있다면 900 knots closure가 되고 400 knots로 날아 가는 비행기를 500 knots의 속도로 따라간다면 100 knots closure가 되는 거죠.


반응형
Posted by J-sean
:
반응형

Detects motions in the vision and saves an image of it as a PNG file. Adjust the sensitivity value if needed.


카메라 영상의 움직임을 감시하고 움직임이 감지된 순간의 영상을 저장한다. sensitivity 값으로 감도를 조절한다.


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
#include <opencv2/opencv.hpp>
 
using namespace std;
using namespace cv;
 
int main(int argc, char** argv)
{
    VideoCapture cap(0);
 
    Mat frameNew;
    Mat frameOld;
    Mat frameDiff;
 
    double min, max;
    int sensitivity = 100;
    int detectionCount = 0;
 
    cap >> frameOld;
 
    while (true)
    {
        cap >> frameNew;
        if (frameNew.empty())
            break;
 
        // Calculates the per-element absolute difference
        // between two arrays or between an array and a scalar.
        absdiff(frameNew, frameOld, frameDiff);
        cvtColor(frameDiff, frameDiff, COLOR_BGR2GRAY);
        minMaxLoc(frameDiff, &min, &max);
 
        if (max > sensitivity)
        {
            cout << "Motion detected. (Max: " << max << ")" << endl;
 
            // For PNG, it can be the compression level from 0 to 9.
            // A higher value means a smaller size and longer compression time.
            vector<int> compression_params;
            compression_params.push_back(IMWRITE_PNG_COMPRESSION);
            compression_params.push_back(3);
            if (imwrite(format("detection_%03d.png", detectionCount++), frameNew, compression_params))
                cout << "Image saved." << endl;
            else
                cout << "Image not saved." << endl;
        }
 
        imshow("Motion Detectoion", frameDiff);
        
        frameNew.copyTo(frameOld);
 
        if (waitKey(10== 27)
            break;
    }
 
    return 0;
}
cs



<frameDiff>


<Detection_XXX.png>




반응형
Posted by J-sean
:
반응형

실패한 미래를 알게된 Thanos는 미래로 넘어와 Avengers와의 싸움을 앞두게 됩니다. 


Thanos: I thought by eliminating half of life, the other half would thrive, but you've shown me that's impossible. And as long as there are those that remember what was, there will always be those that are unable to accept what can be. They will resist.

Ironman: Yep, we're all kinds of stubborn.


Avengers: Endgame



Thanos: I'm thankful. Because now, I know what I must do. I will shred this universe down to its last atom and then, with the stones you've collected for me, create a new one teeming with life that knows not what it has lost but only what it has been given. A grateful universe.


teeming with something은 보통 장소에 대해 쓰이는 표현으로 something(사람이나 동물 등)으로 가득차 있다는 뜻 입니다.


The streets were teeming with tourists.


반응형
Posted by J-sean
:
반응형

출산을 앞두고 있는 과거의 아버지에게 Ironman 자신인 그 아이의 이름은 무엇으로 지을지 물어 봅니다.


Ironman: So, where you at with names?

Howard Stark: Well, if it's a boy, my wife likes Elmonzo.


Avengers: Endgame



Ironman: Huh. Might wanna let that stew awhile. You got time.

Howard Stark: Uh-huh.


stew는 고기와 채소를 넣고 국물이 있게 끓인 요리나 그렇게 음식을 조리하는 과정을 의미하기도 하지만 '생각하다', '마음을 졸이다'라는 뜻을 가집니다.


I’ve been stewing over the problem for a while.



반응형
Posted by J-sean
: