728x90

Android Memo 어플 소스를 RecyclerView 를 이용하여 수정했다.

SQLite 함수 일부분을 수정한 것은 같이 포함시켰다.


DBHelper.java 수정

public class DbHelper extends SQLiteOpenHelper {
    public static final String DATABASE_NAME = "data2";
    public static final String TABLE_NAME = "comments_table";
    public static final String C_ID = "_id";
    public static final String TITLE = "title";
    public static final String TYPE = "type";
    public static final String DETAIL = "description";
    public static final String TIME = "time";
    public static final String DATE = "date";
    public static final int DATABASE_VERSION = 2;

    private final String createDB = "create table if not exists " + TABLE_NAME + " ( "
            + C_ID + " integer primary key autoincrement, "
            + TITLE + " text, "
            + DETAIL + " text, "
            + TYPE + " text, "
            + TIME + " text, "
            + DATE + " text)";

    public DbHelper(Context context){
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(createDB);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("drop table " + TABLE_NAME);
    }

    public Cursor LoadSQLiteDBCursor() {
        SQLiteDatabase db = this.getReadableDatabase();
        db.beginTransaction();
        // Select All Query
        String selectQuery = "SELECT _id,title,type,description,time,date FROM " + TABLE_NAME;
        Cursor cursor = null;
        try {
            cursor = db.rawQuery(selectQuery, null);
            db.setTransactionSuccessful();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            db.endTransaction();
        }
        return cursor;
    }

}


MainActivity.java 수정

import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    Context context;

    SQLiteDatabase db;
    DbHelper mDbHelper;

    private RecyclerView listView;
    private ArrayList<Memo_Item> memoItemList= new ArrayList<>(); // SQLite에서 가져온 원본 데이터 리스트
    RecyclerView.Adapter listViewAdapter; // ListViewAdapter 대신 RecyclerView.Adapter
    RecyclerView.LayoutManager layoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = this.getBaseContext();

        listView = (RecyclerView)findViewById(R.id.commentslist);
        listView.setHasFixedSize(true);

        memoItemList.clear(); // 데이터 초기화
        mDbHelper = new DbHelper(this);
        db= mDbHelper.getReadableDatabase();
        db.beginTransaction();

        Cursor cursor = mDbHelper.LoadSQLiteDBCursor();
        try {
            cursor.moveToFirst();
            System.out.println("SQLiteDB 개수 = " + cursor.getCount());
            while (!cursor.isAfterLast()) {
                addGroupItem(cursor.getLong(0),cursor.getString(1),cursor.getString(2),
                        cursor.getString(3),cursor.getString(4),cursor.getString(5));
                cursor.moveToNext();
            }
            db.setTransactionSuccessful();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
                db.endTransaction();
            }
        }

        // Set Layout Manager
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        listView.setLayoutManager(layoutManager);

        listViewAdapter = new ListViewAdapter(memoItemList, this); // Adapter 생성
        listView.setAdapter(listViewAdapter); // 어댑터를 리스트뷰에 세팅
    }

    public void addGroupItem(Long uid, String title, String memo_type, String detail, String time, String date){
        Memo_Item item = new Memo_Item();
        item.setUid(uid);
        item.setTitle(title);
        item.setMemo_type(memo_type);
        item.setDetail(detail);
        item.setTime(time);
        item.setDate(date);
        memoItemList.add(item);
    }

    @Override
    public void onBackPressed() {
        moveTaskToBack(true);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch(item.getItemId()) {
            case R.id.action_new:
                Intent openCreateNote = new Intent(MainActivity.this, CreateNote.class);
                startActivity(openCreateNote);
                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }

}


Memo_Item.java 클래스 만들기

public class Memo_Item {
    private Long uid;
    private String title; // 제목
    private String memo_type; // 메모 타입
    private String detail; // 내용
    private String time; // 시간
    private String date; // 작성일자

    public Memo_Item() {

    }

    public Memo_Item(Long uid, String title, String memo_type, String detail, String time, String date) {
        this.uid = uid;
        this.title = title;
        this.memo_type = memo_type;
        this.detail = detail;
        this.time = time;
        this.date = date;
    }

    public Long getUid() {
        return uid;
    }

    public void setUid(Long uid) {
        this.uid = uid;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getMemo_type() {
        return memo_type;
    }

    public void setMemo_type(String memo_type) {
        this.memo_type = memo_type;
    }

    public String getDetail() {
        return detail;
    }

    public void setDetail(String detail) {
        this.detail = detail;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }
}


ListViewAdapter 어댑터 클래스 만들기

import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.recyclerview.widget.RecyclerView;

import com.bumptech.glide.Glide;

import java.util.ArrayList;

public class ListViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    Context mContext;
    private ArrayList<Memo_Item> IvList;
    int Position;

    public ListViewAdapter(ArrayList<Memo_Item> items, Context context) {
        IvList = items;
        mContext = context;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_entry, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        // ListView의 getView 부분을 담당하는 메소드
        ((ViewHolder) holder).onBind(IvList.get(position));
    }

    @Override
    public int getItemCount() {
        return IvList.size(); // 데이터 개수 리턴
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        public TextView mTitle;
        public TextView memoType;
        public TextView mDetail;
        public ImageView mImage;
        public TextView mTime;
        public TextView mDate;

        public ViewHolder(View itemView) {
            super(itemView);
            // 화면에 표시될 View 로부터 위젯에 대한 참조 획득
            mTitle = itemView.findViewById(R.id.title);
            memoType = itemView.findViewById(R.id.type);
            mDetail = itemView.findViewById(R.id.Detail);
            mImage = itemView.findViewById(R.id.alarmImage);
            mTime = itemView.findViewById(R.id.time);
            mDate = itemView.findViewById(R.id.date);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Position = getAdapterPosition();
                    Intent intent = new Intent(mContext, View_Note.class);
                    intent.putExtra(mContext.getString(R.string.row_id),IvList.get(Position).getUid());
                    Log.e("rowID", String.valueOf(IvList.get(Position).getUid()));
                    mContext.startActivity(intent);
                }
            });
        }

        public void onBind(Memo_Item item) {
            mTitle.setText(item.getTitle());
            memoType.setText(item.getMemo_type());
            mDetail.setText(item.getDetail());
            int resourceId = R.drawable.ic_action_alarms;
            Glide.with(mContext).load(resourceId).into(mImage);
            mTime.setText(item.getTime());
            mDate.setText(item.getDate());
        }
    }
}


activity_main.xml 수정

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        >

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/commentslist"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </LinearLayout>

</RelativeLayout>


build.gradle 수정

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28


    defaultConfig {
        applicationId "com.tistory.link2me.memo"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.recyclerview:recyclerview:1.0.0'
    implementation 'androidx.cardview:cardview:1.0.0'
    implementation 'gun0912.ted:tedpermission:2.0.0'
    implementation 'com.github.bumptech.glide:glide:3.8.0' // 이미지 라이브러리
}



나머지는 수정한 사항이 없다.

기존 소스코드를 이렇게 수정하면 된다.


memo_src.zip



블로그 이미지

Link2Me

,
728x90

서버가 죽을 수도 있다는 가정하에 코드를 구현했어야 하는데 이를 고려하지 못하니까 어플이 진입도 하지 못하고 죽는 현상이 발생했다.

초보 개발자의 로직 에러다.


이를 보완한 코드 예제다.

서버의 httpd 데몬을 죽여서 전달되는 메시지를 보고, 아래와 같이 failed 라는 글자가 포함되어 있으면, 버전 체크하지 말고 그냥 다음 단계를 실행하도록 했다.

version = Value.getVersionName(mContext);
version = version.replaceAll("[^0-9]", ""); // 버전에서 숫자만 추출

Log.d("WEB", "Response: " + response);
if(response.contains("failed")){ // 서버가 동작하지 않을 때의 메시지에 포함된 걸 체크하라.
    Log.e("WEB", "Server isConnected failed.");
    startActivity(new Intent(getApplication(), MainMenu.class));
    finish();
} else {
    Log.e("WEB", "Server Version : " + response);
    Response = response.replaceAll("[^0-9]", ""); // 버전에서 숫자만 추출
    if (Integer.parseInt(version) < Integer.parseInt(Response)) { // 서버 버전이 더 높으면
        UpgradeProcess();
    } else {
        startActivity(new Intent(getApplication(), MainMenu.class));
        finish();
    }
}


블로그 이미지

Link2Me

,
728x90

안드로이드 메모 어플을 https://github.com/DomHeal/Android-Memo-Application 에서 받아서 코드를 API 28 (Android 9) 에서 동작하도록 수정한 코드이다.

ListView 에 일렬로 보여주는 아주 간단한 메모 코드다. SQLite DB를 사용하여 데이터를 로컬 DB에 저장하고 보여주는 코드이므로 달력 형태로 보여주는 건 아니다.

간단하게 SQLite DB 사용법 익히는 용도로 좋은 예제인거 같다.


memo.zip


앱 build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28


    defaultConfig {
        applicationId "com.tistory.link2me.memo"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
}


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.tistory.link2me.memo">

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

    <application
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:usesCleartextTraffic="true" <!-- 서버와 http 통신할 경우 추가해야 정상동작 -->
        android:theme="@style/AppTheme">
        <activity android:name=".Alert"></activity>
        <activity android:name=".Edit_Note" />
        <activity android:name=".View_Note" />
        <activity android:name=".CreateNote" />
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver
            android:name=".AlarmReceiver"
            android:enabled="true"
            android:exported="true" />
    </application>

</manifest>
 


MainActivity.java

import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    SQLiteDatabase db;
    DbHelper mDbHelper;
    ListView list;

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

        list = (ListView)findViewById(R.id.commentslist);
        mDbHelper = new DbHelper(this);
        db= mDbHelper.getWritableDatabase();
        final ImageView alarmImage = (ImageView) findViewById(R.id.alarmImage);

        String[] from = {mDbHelper.TITLE, mDbHelper.DETAIL, mDbHelper.TYPE, mDbHelper.TIME, mDbHelper.DATE};
        final String[] column = {mDbHelper.C_ID, mDbHelper.TITLE, mDbHelper.DETAIL, mDbHelper.TYPE, mDbHelper.TIME, mDbHelper.DATE};
        int[] to = {R.id.title, R.id.Detail, R.id.type, R.id.time, R.id.date};

        final Cursor cursor = db.query(mDbHelper.TABLE_NAME, column, null, null ,null, null, null);
        final SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.list_entry, cursor, from, to, 0);

        list.setAdapter(adapter);
        list.setOnItemClickListener(new AdapterView.OnItemClickListener(){
            public void onItemClick(AdapterView<?> listView, View view, int position,
                                    long id){
                Intent intent = new Intent(MainActivity.this, View_Note.class);
                intent.putExtra(getString(R.string.rodId), id);
                startActivity(intent);
            }

        });

    }

    @Override
    public void onBackPressed() {
        moveTaskToBack(true);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch(item.getItemId()) {
            case R.id.action_new:
                Intent openCreateNote = new Intent(MainActivity.this, CreateNote.class);
                startActivity(openCreateNote);
                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }

}


나마저 코드와 xml 파일은 첨부파일을 참조해서 프로젝트 생성하고 모듈 추가해서 코드를 덮어쓰거나 변형하여 덮어쓰기 하면 동작되는 걸 확인할 수 있다.

ListView 를 사용한 코드인데 RecyclerView 로 변경하는 건 나중에 기회되면 수정해서 올려볼 생각이다.


참고자료

안드로이드 모듈 추가 방법 https://link2me.tistory.com/1369 참조



블로그 이미지

Link2Me

,
728x90

개발용 서버에서 기능 테스트를 할 때 안전하게 전화번호 부분을 일괄 임시번호로 변경하면 개인정보 보호에 더 좋을 수 있어서 일괄 변경하는 기능을 만들어서 적용해봤다.

 

<?php
require_once '../sessionChk.php'// 세션 체크
require_once "../config/dbconnect.php";
 
$i = 0;
 
$sql = "SELECT idx FROM SYS_MEMBER";
$result = mysqli_query($db,$sql);
while($row = mysqli_fetch_row($result)){
    $i++;
    $mobileNO = '010-1000-'.sprintf('%04d',$i);
    $mobileNO = str_replace('-','',$mobileNO);
    $sql = "UPDATE SYS_MEMBER SET mobileNO='$mobileNO' WHERE idx=".$row[0];
    mysqli_query($db,$sql);
}
 
echo $i.' rows Updated';
 
?>
 

 

 

 

 

<?php
if(!isset($_SESSION)) {
    session_start();
}
require_once 'path.php';// root 폴더를 기준으로 상대적인 경로 자동 구하기
require_once $g['path_root'].'sessionChk.php';
require_once $g['path_root'].'deviceChk.php';
if($mtype == 3){
    require_once $g['path_root'].'ipFiltering.php';
}
require_once $g['path_config'].'dbconnect.php';
require_once $g['path_class'].'dbDataClass.php';
$d = new DBDataClass();
 
$sql ="select * from members";
$result=mysqli_query($db,$sql);
$i=0;
while($row=mysqli_fetch_array($result)){
    $i++;
    if(strlen($row['mobileNO'])>0){
        $telNO = TelNumSplitArr($row['mobileNO'])."0001".sprintf("%04d",$i);
        echo $telNO.'<br/>';
        $QKEY ="mobileNO='".$telNO."'";
        $d->getDbUpdate('members',$QKEY,'uid="'.$row['uid'].'"');
    }
 
    if(strlen($row['officeNO'])>0){
        $officeNO = TelNumSplitArr($row['officeNO'])."0001".sprintf("%04d",$i);
        //echo $officeNO.'<br/>';
        $QKEY ="officeNO='".$officeNO."'";
        $d->getDbUpdate('members',$QKEY,'uid="'.$row['uid'].'"');
    }
 
}
 
//전화번호를 정규식을 이용하여 지역번호, 010과 같은 앞자리는 그대로 두기 위해서 앞부분만 추출한다.
function TelNumSplitArr($tel){
    $tel = preg_replace("/[^0-9]/"""$tel);    // 숫자 이외 제거
    if (substr($tel,0,2)=='02')
        return preg_replace("/([0-9]{2})([0-9]{3,4})([0-9]{4})$/""\\1"$tel);
    else
        return preg_replace("/([0-9]{3})([0-9]{3,4})([0-9]{4})$/""\\1"$tel);
}
 
?> 

 

블로그 이미지

Link2Me

,
728x90
You can not use .equals() to compare int.
But you can use == also to compare Integer.
Integer and int are different. Integer is a class and int is a primitive type.

public class IntegerToString {
    public static void main(String[] args) {
        // declare the Integer object
        Integer intValue = new Integer(100);
        // Declare the Object
        Object obj = new Integer(100);
        // test for equality
        if(intValue.equals(obj)){
            System.out.println("Integer is equals to the object.");
        }
        else{
            System.out.println("Not equal, something is wrong.");
        }
    }
}


결과 : Integer is equals to the object.


난독화 가이드에 String 비교시 == 를 사용하지 말라고 되어 있어서

if (deviceFound == null) {
대신에
if (!"".equals(deviceFound)) {
로 변경해서 난독화 하지 않은 상태로 시도했더니 에러가 발생한다.


즉, null 은 객체가 아니라서 equals 로 비교할 수가 없다.

!"".equals(deviceFound) 이 null 을 대신할 수는 없다는 것이다.


!"".equals(st)
형태로 많이 쓴다고 되어 있어서 테스트를 해봤는데 잘못된 정보다.

null 비교는 == 연산자를 사용하면 된다.


equals는 기본적으로 값 비교를 한다.
== 는 주소값을 비교한다.
String 객체를 == 연산자로 비교하면 '주소값' 을 비교한다.
비교 대상 중 primitive type(int) 의 변수가 하나라도 있다면, == 연산자는 값으로 비교한다.


private String IPSubnetMask(String msgArray){
    if(msgArray.contains("/")){
        String[] input_ipsubnet = msgArray.split("/"); // / 기호로 분리하라.
        String ipaddress = input_ipsubnet[0];
        String subnetMask = input_ipsubnet[1];
        if(IP_Validation.matcher(ipaddress).matches()) {
            if(Integer.parseInt(subnetMask)< 23) {
                return "3"; // 서브넷 마스크 확인 필요
            } else {
                return "1"; // 정상
            }
        } else {
            return "2"; // IP주소 비정상 입력
        }
    } else {
        return "0"; // 입력이 잘못되었다는 표시
    }
}


위 함수에서는 결과를 숫자가 아닌 문자 숫자로 반환하도록 했다.

String result = IPSubnetMask(ipsubnet);
if(result.equals("1")){

}

와 같이 equals 로 값 비교하면 된다.



'안드로이드 > Java 문법' 카테고리의 다른 글

[Java] Convert Month String to Integer  (0) 2019.10.14
Java ArrayList 함수 만들기  (0) 2019.10.02
공백으로 문자열 분리  (0) 2019.09.11
Java 제네릭(Generic)  (0) 2019.08.27
Java 추상 클래스  (0) 2019.08.19
블로그 이미지

Link2Me

,
728x90

http://www.jcraft.com/jsch/ 사이트에서 파일을 다운로드 받는다.



다운로드 받은 파일을 libs 폴더에 복사/이동한다.


앱 build.gradle 에 추가한다.


dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'gun0912.ted:tedpermission:2.0.0'
    implementation 'com.android.volley:volley:1.1.1'
    implementation 'com.google.android.material:material:1.0.0'
    implementation files('libs/jsch-0.1.55.jar')

}


Sync Now 를 해주면 라이브러리 추가가 완료된다.

블로그 이미지

Link2Me

,
728x90

PHP 에서 문자를 발송할 때 ***님이라고 이름을 변경해서 보내는 문자를 할 때 좋은 기능이 될 거 같아서 적어둔다.


<?php
$str = '안녕하세요. [name]님. 오늘 날씨가 참 좋습니다. 이번 모임은 OO에서 개최합니다.';
$arr = array('홍길동','이순신','김구','을지문덕');

foreach($arr as $name){ // 배열에만 동작하는 반복문 foreach문
    // 콜백을 이용한 정규 표현식 검색과 치환을 수행
    // preg_replace_callback ( $pattern , $callback , $str )
    // 매치가 발견되면 새 str 반환되고, 그렇지 않으면 변경되지 않은 str 가 반환
    $text_message = preg_replace_callback('#\[name\]#',
        function($match) use ($name) {
            return replaceForm($name);
        }, $str);
    echo $text_message.'<br/>';
}

function replaceForm($name) {
    static $idx = 0;
    $idx++;
    return str_replace('{{idx}}', $idx, $name);
}

?>


블로그 이미지

Link2Me

,
728x90

토트넘과 크리스탈 팰리스 전에서 손흥민이 2골을 넣어 토트넘이 4:0 으로 이겼다.

환상적인 골이 있어서 유투브 링크를 걸어둔다.



블로그 이미지

Link2Me

,
728x90

안드로이드 배터리 잔량 정보를 표시하는 코드이다.


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv_battery"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:text="배터리 잔량"
        />

</LinearLayout>

import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.Bundle;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

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

        TextView textView = findViewById(R.id.tv_battery);

        // 안드로이드의 BatteryManager가 고정 인텐트를 사용하고 있기 때문에
        // 실제 BroadcastReceiver를 등록 할 필요가 없다.

        IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        Intent batteryStatus = registerReceiver(null, ifilter);

        int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
        int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);

        float batteryPct = level / (float)scale;
        String value = String.valueOf((int)(batteryPct*100));

        textView.setText("Battery Level Remaining: " + value + "%");
    }
}


블로그 이미지

Link2Me

,
728x90

자바에서 공백으로 문자열 분리하는 예제로 MIH 다음에 나오는 IP주소를 얻고 싶은 거다.

split(정규식) 을 사용해서 문자열을 분리해서 얻는다.

먼저 MIH 가 반드시 들어가는 줄인지 체크한 다음에 들어간 줄이면, MIH 이후의 문자열을 공백으로 분리해서 추출한 것과 바로 공백으로 구분해서 값을 추출했다.


public class Split_ex_01 {

    public static void main(String[] args) {
        String str ="    MIH     10.2.224.84      255.255.224.0 (19)   10.2.224.1       Intf(MIH)      ";
        str= str.trim(); // 문자열 앞뒤 공백 제거
        int stlocation = str.indexOf("MIH");
        int endlocation = str.length();
        String temp = str.substring(stlocation+3, endlocation).trim();
        System.out.println(temp);
        String[] part = temp.split("\\s{1,}"); // 공백으로 문자열 분리
        System.out.println(part[0]);
       
        String[] parts = str.split("\\s{1,}");
// 공백으로 문자열 분리       

        System.out.println(parts[1]);
    }
}


'안드로이드 > Java 문법' 카테고리의 다른 글

Java ArrayList 함수 만들기  (0) 2019.10.02
자바 null 비교, String 비교, 정수 비교  (0) 2019.09.20
Java 제네릭(Generic)  (0) 2019.08.27
Java 추상 클래스  (0) 2019.08.19
[Java] 다형성  (0) 2019.06.30
블로그 이미지

Link2Me

,
728x90

유투브 강좌를 보고 따라서 코드 적어가며 테스트하고 적어둔다.

유투브 동영상 : https://www.youtube.com/watch?v=OTNuxe_ihtM&t=774s

 

 

각각 서로 다른 파일로 생성하여 테스트 해야 하는데 하나의 파일로 작성하여 테스트했다.

- 인터페이스 타입의 변수로 인터페이스를 구현한 클래스의 인스턴스를 참조할 수 있다.

- 인터페이스를 메소드의 매개변수 타입으로 지정할 수 있다.

interface OnFoundListener {
    // 1. Create a callback interface.
    void onFound(String result);
}
 
class ClassA {
    // 2. Create a class as a worker.
    public void findAGirl(OnFoundListener onFoundListener ) {
        for(int i=0; i < 5; i++) {
            try {
                Thread.sleep(100);
                System.out.println("A is trying find a girl for you " + i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        onFoundListener.onFound("A found a girl for you.");
        // A found nothing, so that assign this job for B.
        //ClassB classB = new ClassB();
        //classB.findACuteGirl(onFoundListener);
    }
 
}
 
public class InerfaceWorld {
    public static void main(String[] args) {
        ClassA classA = new ClassA();
        classA.findAGirl(new OnFoundListener() {
            @Override
            public void onFound(String result) {
                System.out.println(result);
            }
        });
    }
}
 

메소드를 호출하는 쪽에서는 메소드의 내용에 관계없이 선언부만 알면 되기 때문에 이를 이용하여 프로그램을 작성할 수 있다. 동시에 다른 한 쪽에서는 인터페이스를 구현하는 클래스를 작성하도록 하여, 인터페이스를 구현하는 클래스가 작성될 때까지 기다리지 않고도 양쪽에서 동시에 개발을 진행할 수 있다.

 

 

 

 

 

interface OnFoundListener {
    // 1. Create a callback interface.
    void onFound(String result);
}
 
class ClassA {
    // 2. Create a class as a worker.
    public void findAGirl(OnFoundListener onFoundListener ) {
        for(int i=0; i < 5; i++) {
            try {
                Thread.sleep(100);
                System.out.println("A is trying find a girl for you " + i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //onFoundListener.onFound("A found a girl for you.");
        // A found nothing, so that assign this job for B.
        ClassB classB = new ClassB();
        classB.findACuteGirl(onFoundListener);
    }
}
 
class ClassB {
    public void findACuteGirl(OnFoundListener onFoundListener ) {
        for(int i=0; i < 5; i++) {
            try {
                Thread.sleep(100);
                //System.out.println("A is trying find a girl for you " + i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        onFoundListener.onFound("A found a cute girl for you.");
    }
}
 
public class InterfaceWorld2 {
    public static void main(String[] args) {
        ClassA classA = new ClassA();
        classA.findAGirl(new OnFoundListener() {
            @Override
            public void onFound(String result) {
                System.out.println(result);
            }
        });
    }
}
 
 

 

 

'안드로이드 > Interface' 카테고리의 다른 글

Java Interface 예제  (0) 2019.11.18
Android Interface AsyncTask 예제  (0) 2019.11.05
Java 인터페이스(interface) 개요  (0) 2019.08.20
Android Interface 예제 ★★★  (0) 2018.08.22
Android Interface 예제 1  (0) 2018.08.20
블로그 이미지

Link2Me

,