platform-tools 설치확인

D:\slsolution\platform-tools

 

 - 안드로이드 스튜디오가 설치된 PC와 USB 연결
 - 스마트폰의 화면을 끔
 - 어플에서 특정 기능을 테스트하는 경우, 어플을 킨 후 테스트할 항목을 진행 시킨 후에 화면을 끔

 

adb devices 디바이스 연결확인

 

  1. 다음 명령어를 실행하여 강제로 시스템을 유휴 모드로 지정합니다.
     
        $ adb shell dumpsys deviceidle force-idle
        
  2. 준비가 되면 다음 명령어를 실행하여 유휴 모드를 종료합니다.
     
        $ adb shell dumpsys deviceidle unforce
        
  3. 다음 명령어를 실행하여 기기를 다시 활성화합니다.
     
        $ adb shell dumpsys battery reset
          

popupwindow.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="300dp"
    android:gravity="center"
    android:background="#E1000000"
    android:padding="10px">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="주의"
        android:textStyle="bold"
        android:textSize="30sp"
        android:textColor="#ABF106"/>
    <TextView
        android:layout_margin="30px"
        android:id="@+id/popup_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=""
        android:textStyle="bold"
        android:textSize="38sp"
        android:textColor="#FCFCFC"/>

    <Button
        android:id="@+id/closePopupBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="확인"
        />
</LinearLayout>

메인 엑티비티의 레이아웃 id도 필요합니다. 

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/mainLayout"
    tools:context=".activity.MainActivity">

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


</androidx.constraintlayout.widget.ConstraintLayout>

mainLayout 이라고 심플하게 만들어 줬습니다.

 

mainActivity.java 

public void checkWebRoadEvent(String data0, String data1, String data2) {

        ConstraintLayout linearLayout1 = (ConstraintLayout) findViewById(R.id.mainLayout);
        LayoutInflater layoutInflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        final View customView = layoutInflater.inflate(R.layout.popupwindow, null);
        Button closeBtn = (Button) customView.findViewById(R.id.closePopupBtn);
        TextView textview = (TextView) customView.findViewById(R.id.popup_text);
        textview.setText(Messages[0] + "지도를 확인하세요.");
        popupWindow = new PopupWindow(customView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        final Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.rotate);
        customView.startAnimation(animation);
        popupWindow.showAtLocation(linearLayout1, Gravity.TOP, 0, 0);
        popupWindow.setBackgroundDrawable(new BitmapDrawable());


        final Handler handler = new Handler() {
            public void handleMessage(Message msg) {
                // 원래 하려던 동작 (UI변경 작업 등)
                final Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.close);
                customView.startAnimation(animation);

                Handler mhandler = new Handler();
                mhandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (popupWindow != null) {
                            popupWindow.dismiss();
                            popupWindow = null;
                        }
                    }
                }, 500);
            }
        };

        final Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                TimerTask task = new TimerTask() {
                    @Override
                    public void run() {
                        Message msg = handler.obtainMessage();
                        handler.sendMessage(msg);
                        Log.d("lati", "check ");
                    }
                };

                Timer timer = new Timer();
                timer.schedule(task, 5000);
            }
        });


        closeBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Message msg = handler.obtainMessage();
                handler.sendMessage(msg);
                Log.d("lati", "check ");

            }
        });
        thread.start();
        startSound();
        
        Log.d("dialogStart", "get Show Road Event");
    }

timer , runable , thread  사용은 다른곳 참고 부탁드릴게요~ 저도 완벽한 개념을 알고 쓴게 아니라서 ㅎㅎ 저장용입니다.
popupwindow 에서 타이머 사용시 뷰를 변경할 수 없다는 오류가 뜨는데 핸들러를 통하여 한번 돌아서 사용하시면 될것 같습니다. 

 

사운드

알람은 raw 패키지 폴더 생성하고 거기에 넣으셔야합니다.

기본 알람도 사용할 수 있습니다. 따로 안적을게요~

    public void startSound() {
        MediaPlayer player = MediaPlayer.create(this, R.raw.alarm1);
        player.start();
    }

애니메이션

anum 패키지 폴더 생성후

오픈시에는 위에서 밑으로 내려오게끔 
클로즈는 오른쪽으로 없어지게 만들었습니다.

 

open.xml

<?xml version="1.0" encoding="utf-8"?>

<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromYDelta="-100%"
    android:toYDelta="0">
</translate>

 

close.xml

<?xml version="1.0" encoding="utf-8"?>

<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromXDelta="0"
    android:toXDelta="100%">
</translate>

 

 

객체생성

public class WarningData {
    public enum WarningValue {
        SAFE, // 안전
        ATTENTION, // 관심
        CAUTION, // 주의
        WARNING, // 경고
        DANGER // 위험
    }

    private String Time;
    private String vertialdistance;
    private String ttcp;
    private WarningValue warning;

    public WarningData(String time, String vertialdistance, String ttcp, WarningValue warning) {
        Time = time;
        this.vertialdistance = vertialdistance;
        this.ttcp = ttcp;
        this.warning = warning;
    }

    public String getTime() {
        return Time;
    }

    public void setTime(String time) {
        Time = time;
    }

    public String getVertialdistance() {
        return vertialdistance;
    }

    public void setVertialdistance(String vertialdistance) {
        this.vertialdistance = vertialdistance;
    }

    public String getTtcp() {
        return ttcp;
    }

    public void setTtcp(String ttcp) {
        this.ttcp = ttcp;
    }

    public WarningValue getWarning() {
        return warning;
    }

    public void setWarning(WarningValue warning) {
        this.warning = warning;
    }
}

 

Utill class 생성

public class Util {
    public static WarningData.WarningValue getWarningValue(int risk) {
        WarningData.WarningValue value = WarningData.WarningValue.SAFE;
        switch (risk) {
            case 0:
                value = WarningData.WarningValue.SAFE;
                break;
            case 1:
                value = WarningData.WarningValue.ATTENTION;
                break;
            case 2:
                value = WarningData.WarningValue.CAUTION;
                break;
            case 3:
                value = WarningData.WarningValue.WARNING;
                break;
            case 4:
                value = WarningData.WarningValue.DANGER;
                break;
        }
        return value;
    }
}

 

통신을 통해 받아온 risk는 0,1,2,3,4 입니다.

   int risk = worningObject.getRiskMin();
                WarningData.WarningValue warningValue = Util.getWarningValue(risk);
                 warningData= new WarningData(formatDate,String.valueOf(worningObject.getDistanceMin()),String.valueOf(worningObject.getTtcpMin()),warningValue);

받아온 데이터는 객체를 통해 전달됩니다.

 

 

어뎁터사용 예시

        int color = context.getResources().getColor(R.color._2086c0);
        if (item.getWarning() == WarningData.WarningValue.SAFE) {
            holder.warningText.setText("안전");
            color = context.getResources().getColor(R.color._2086c0);
        } else if (item.getWarning() == WarningData.WarningValue.ATTENTION) {
            holder.warningText.setText("관심");
            color = context.getResources().getColor(R.color._179033);
        } else if (item.getWarning() == WarningData.WarningValue.CAUTION) {
            holder.warningText.setText("주의");
            color = context.getResources().getColor(R.color._e9c71d);
        } else if (item.getWarning() == WarningData.WarningValue.WARNING) {
            holder.warningText.setText("경고");
            color = context.getResources().getColor(R.color._c05b20);
        } else if (item.getWarning() == WarningData.WarningValue.DANGER) {
            holder.warningText.setText("위험");
            color = context.getResources().getColor(android.R.color.holo_red_dark);
        }

        holder.warningText.setTextColor(color);

 

 

엑티비티에서의 사용 예시

                if (infos != null) {
                    if (infos.getWarning() == SAFE) {
                        levelImage.setImageResource(R.drawable.warning_0);
                    } else if (infos.getWarning() == ATTENTION) {
                        levelImage.setImageResource(R.drawable.warning_1);
                    } else if (infos.getWarning() == CAUTION) {
                        levelImage.setImageResource(R.drawable.warning_2);
                    } else if (infos.getWarning() == WARNING) {
                        levelImage.setImageResource(R.drawable.warning_3);
                    } else if (infos.getWarning() == DANGER) {
                        levelImage.setImageResource(R.drawable.warning_4);
                    }
                }

 

 

double locationX = location.getLongitude();

 

받아온 좌표는 double형입니다.

String formatStringLocationX = String.format(Locale.KOREA,"%.6f", locationX);
locationX = Double.parseDouble(formatStringLocationX);

만약 좌표가 123.456 이라면 

Locale 에 따라 float 타입이 .이 콤마로 표시될 수 있다고 합니다. 이점 참고하고 작업하시길..

 

참고 블로그
fumin.tistory.com/299

 

[안드로이드] String Format 사용시 주의사항

안녕하세요 푸민입니다. 이번에 개발하다가 생긴 이슈인 String 객체의 format() 메소드에 대해서 포스팅합니다. String.format() 의 경우 많이 사용하지는 않지만 가끔 Url 같이 긴 String 을 작성할때 사��

fumin.tistory.com

 

build.Gradle 의 dependencies 

 

  implementation 'com.google.code.gson:gson:2.8.1'

gson 추가 

 

ResponseHashMap 객체를 gson 에서 받아오는 데이터의 파라미터로 만들어줍니다.

public class ResponseHashMap  {

    private String hashCode0;
    private String hashCode1;
    private String hashCode2;
    private String hashCode3;
    private String hashCode4;
    private String hashCode5;
    private String hashCode6;
    private String hashCode7;
    private String hashCode8;
    private String hashCode9;

    public ResponseHashMap(String hashCode0, String hashCode1, String hashCode2, String hashCode3, String hashCode4, String hashCode5, String hashCode6, String hashCode7, String hashCode8, String hashCode9) {
        this.hashCode0 = hashCode0;
        this.hashCode1 = hashCode1;
        this.hashCode2 = hashCode2;
        this.hashCode3 = hashCode3;
        this.hashCode4 = hashCode4;
        this.hashCode5 = hashCode5;
        this.hashCode6 = hashCode6;
        this.hashCode7 = hashCode7;
        this.hashCode8 = hashCode8;
        this.hashCode9 = hashCode9;
    }

    public String getHashCode0() {
        return hashCode0;
    }

    public void setHashCode0(String hashCode0) {
        this.hashCode0 = hashCode0;
    }

    public String getHashCode1() {
        return hashCode1;
    }

    public void setHashCode1(String hashCode1) {
        this.hashCode1 = hashCode1;
    }

    public String getHashCode2() {
        return hashCode2;
    }

    public void setHashCode2(String hashCode2) {
        this.hashCode2 = hashCode2;
    }

    public String getHashCode3() {
        return hashCode3;
    }

    public void setHashCode3(String hashCode3) {
        this.hashCode3 = hashCode3;
    }

    public String getHashCode4() {
        return hashCode4;
    }

    public void setHashCode4(String hashCode4) {
        this.hashCode4 = hashCode4;
    }

    public String getHashCode5() {
        return hashCode5;
    }

    public void setHashCode5(String hashCode5) {
        this.hashCode5 = hashCode5;
    }

    public String getHashCode6() {
        return hashCode6;
    }

    public void setHashCode6(String hashCode6) {
        this.hashCode6 = hashCode6;
    }

    public String getHashCode7() {
        return hashCode7;
    }

    public void setHashCode7(String hashCode7) {
        this.hashCode7 = hashCode7;
    }

    public String getHashCode8() {
        return hashCode8;
    }

    public void setHashCode8(String hashCode8) {
        this.hashCode8 = hashCode8;
    }

    public String getHashCode9() {
        return hashCode9;
    }

    public void setHashCode9(String hashCode9) {
        this.hashCode9 = hashCode9;
    }
}

 

아래와 같이 통신받은 데이터는 JSON 데이터로 받아와 자동으로 객체화 시켜줍니다.

String datas = null;
Gson gson = new Gson();
ResponseHashMap hashMap = gson.fromJson(data, ResponseHashMap.class);
        
datas = hashMap.getHashCode0();

 

아래 블로그에 더욱 자세한 내용이 설명되어 있습니다. 

 

galid1.tistory.com/501

 

 

 

 

AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

인터넷과 로케이션 관련 권한을 추가해줍니다.

 

 

 public boolean startTracker() {
        
        try {
      	    //GPS,NetWork 프로바이더 사용여부
            boolean isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            if (!isGpsEnabled && !isNetworkEnabled) {
                Log.e(LOG_HEAD, "GPS, NETWORK Disable");
                return false;
            } else {
           
                if (context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                        && context.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
             
                    return false;
                }
                if (isNetworkEnabled) {
                    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME, MIN_DISTANCE, locationListener);
                }
                if (isGpsEnabled) {
                    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME, MIN_DISTANCE, locationListener);
                }


                return true;
            }

로케이션 관련 클래스에 함수설정 

AndroidManifest.xml에서 

 

퍼미션설정해주시고 

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

 

 

Application 안에 추가해줍니다.

android:usesCleartextTraffic="true"

 

 

 

package kr.co.sl.safeportcar.activity;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.ArrayList;

import kr.co.sl.safeportcar.R;
import kr.co.sl.safeportcar.data.GpsInfo;

public class WorkListAdapter extends BaseAdapter {

    private ArrayList<GpsInfo> itemList;

    private Context context;

    public WorkListAdapter(Context context) {
        this.context = context;
        itemList = new ArrayList<>();
    }

    @Override
    public int getCount() {
        return itemList.size();
    }

    @Override
    public Object getItem(int position) {
        return itemList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        View cView = convertView;
        ViewHolder holder;
        if (cView == null) {
            cView = LayoutInflater.from(context).inflate(R.layout.list_item_work, parent, false);
            holder = new ViewHolder(cView);
            cView.setTag(holder);

        } else {
            holder = (ViewHolder) cView.getTag();
        }

        GpsInfo item = itemList.get(position);
        holder.indexText.setText("" + (itemList.size() - position));
        holder.timeText.setText(item.getTime());
        String location = item.getLat() + "\n" + item.getLon();
        holder.locationText.setText(location);
        holder.speedText.setText(String.valueOf(item.getSpeed()));
        holder.directText.setText(String.valueOf(item.getDirect()));
        return cView;
    }

    public void addItem(GpsInfo gpsInfo) {
        itemList.add(0, gpsInfo);
        notifyDataSetChanged();
    }

    class ViewHolder {

        TextView indexText;
        TextView timeText;
        TextView locationText;
        TextView speedText;
        TextView directText;

        public ViewHolder(View view) {
            indexText = view.findViewById(R.id.workListItemIndexText);
            timeText = view.findViewById(R.id.workListItemTimeText);
            locationText = view.findViewById(R.id.workListItemLocationText);
            speedText = view.findViewById(R.id.workListItemSpeedText);
            directText = view.findViewById(R.id.workListItemDirectText);
        }
    }
}

addItem 에서 
itemList.add(0, gpsInfo);
add(gpsInfo) -> add(0,gpsInfo) 로 바꿔줍니다.

 

하지만 Index 번호가 아래로 쌓입니다.

 

holder.indexText.setText("" + (itemList.size() - position));

위와 같이 텍스트를 변경하시면 리스트가 0번 index로 계속 쌓이고 해당 인덱스의 포지션이 +1씩 증가하면서 쌓이게 됩니다.

 

리스트를 아에 맨 아래부터 쌓고 싶으신 분들은 

listView 가 있는 xml에

android:stackFromBottom="true"

를 추가하시면 되겠습니다.

+ Recent posts