URL 상의 mp3 스트리밍

프로그래밍/Android (Java)|2018. 5. 30. 12:46
반응형


Filayout : testaudiofromurl.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/widget31"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
    <EditText
        android:id="@+id/EditTextSongURL"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:ems="10"
        android:height="100dp"
        android:lines="3"
        android:maxLines="3"
        android:minLines="1" >

        <requestFocus />

        <requestFocus />

    </EditText>

    <ImageButton
        android:id="@+id/ButtonTestPlayPause"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/EditTextSongURL"
        android:layout_centerHorizontal="true"
        android:contentDescription="TestPlayPause"
        android:onClick="onClick"/>

    <SeekBar
        android:id="@+id/SeekBarTestPlay"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/ButtonTestPlayPause" />
    
 </RelativeLayout> 

//Code ::Mainactivity.java

package com.example.androidtest2;
import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.SeekBar;

public class testaudiofromurl extends Activity implements OnClickListener, OnTouchListener, OnCompletionListener, OnBufferingUpdateListener{

 private ImageButton buttonPlayPause;
 private SeekBar seekBarProgress;
 public EditText editTextSongURL;

 private MediaPlayer mediaPlayer;
 private int mediaFileLengthInMilliseconds; // this value contains the song duration in milliseconds. Look at getDuration() method in MediaPlayer class

 private final Handler handler = new Handler();

 /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.testaudiofromurl);
        initView();
    }
    
    /** This method initialise all the views in project*/
    private void initView() {
  buttonPlayPause = (ImageButton)findViewById(R.id.ButtonTestPlayPause);
  buttonPlayPause.setOnClickListener(this);

  seekBarProgress = (SeekBar)findViewById(R.id.SeekBarTestPlay); 
  seekBarProgress.setMax(99); // It means 100% .0-99
  seekBarProgress.setOnTouchListener(this);
  editTextSongURL = (EditText)findViewById(R.id.EditTextSongURL);
  editTextSongURL.setText("http://tiennamdinh.freevnn.com/mp3voa/nguyenvanthanh.mp3");

  mediaPlayer = new MediaPlayer();
  mediaPlayer.setOnBufferingUpdateListener(this);
  mediaPlayer.setOnCompletionListener(this);
 }

 /** Method which updates the SeekBar primary progress by current song playing position*/
    private void primarySeekBarProgressUpdater() {
     seekBarProgress.setProgress((int)(((float)mediaPlayer.getCurrentPosition()/mediaFileLengthInMilliseconds)*100)); // This math construction give a percentage of "was playing"/"song length"
  if (mediaPlayer.isPlaying()) {
   Runnable notification = new Runnable() {
          public void run() {
           primarySeekBarProgressUpdater();
    }
      };
      handler.postDelayed(notification,1000);
     }
    }

 @Override
 public void onClick(View v) {
  if(v.getId() == R.id.ButtonTestPlayPause){
    /** ImageButton onClick event handler. Method which start/pause mediaplayer playing */
   try {
    mediaPlayer.setDataSource(editTextSongURL.getText().toString()); // setup song from http://www.hrupin.com/wp-content/uploads/mp3/testsong_20_sec.mp3 URL to mediaplayer data source
    mediaPlayer.prepare(); // you must call this method after setup the datasource in setDataSource method. After calling prepare() the instance of MediaPlayer starts load data from URL to internal buffer. 
   } catch (Exception e) {
    e.printStackTrace();
   }

   mediaFileLengthInMilliseconds = mediaPlayer.getDuration(); // gets the song length in milliseconds from URL

   if(!mediaPlayer.isPlaying()){
    mediaPlayer.start();
    buttonPlayPause.setImageResource(R.drawable.ic_launcher);
   }else {
    mediaPlayer.pause();
    buttonPlayPause.setImageResource(R.drawable.ic_launcher);
   }

   primarySeekBarProgressUpdater();
  }
 }

 @Override
 public boolean onTouch(View v, MotionEvent event) {
  if(v.getId() == R.id.SeekBarTestPlay){
   /** Seekbar onTouch event handler. Method which seeks MediaPlayer to seekBar primary progress position*/
   if(mediaPlayer.isPlaying()){
       SeekBar sb = (SeekBar)v;
    int playPositionInMillisecconds = (mediaFileLengthInMilliseconds / 100) * sb.getProgress();
    mediaPlayer.seekTo(playPositionInMillisecconds);
   }
  }
  return false;
 }

 @Override
 public void onCompletion(MediaPlayer mp) {
   /** MediaPlayer onCompletion event handler. Method which calls then song playing is complete*/
  buttonPlayPause.setImageResource(R.drawable.ic_launcher);
 }

 @Override
 public void onBufferingUpdate(MediaPlayer mp, int percent) {
  /** Method which updates the SeekBar secondary progress by current song loading from URL position*/
  seekBarProgress.setSecondaryProgress(percent);
 }
}



[출처] http://www.droidcourse.com/2014/07/android-play-audio-file-from-url.html


반응형

댓글()

EditText 에 focus 주고 (커서 이동) 소프트 키보드 자동 띄우기

프로그래밍/Android (Java)|2018. 4. 11. 17:44
반응형

1. EditText 에 포커스 주기


SearchInput = (RelativeLayout) findViewById(R.id.SearchInput);

SearchInput.setVisibility(View.VISIBLE);

SearchInput.requestFocus();




2. 현재 포커스 위치한곳에 소프트 키보드 띄우기


1) 키보드 사용 표시


InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);

imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);



2) 키보드 사용을 숨기기


InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);

imm.hideSoftInputFromWindow(view.getWindowToken(),0); 



반응형

댓글()

Layout 에 관한 모든것

프로그래밍/Android (Java)|2018. 4. 10. 16:09
반응형

LinearLayout (순서대로 정렬)

https://recipes4dev.tistory.com/89



RelativeLayout (상대적 위치 잡기)

http://recipes4dev.tistory.com/126



FrameLayout (레이아웃 겹치기 / 아래 있는 View 가 앞으로 나옴)

https://recipes4dev.tistory.com/127




반응형

댓글()

EditText 입력 후 Button 누르면 Toast 로 출력시키는 예제

프로그래밍/Android (Java)|2018. 4. 10. 08:31
반응형

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content" >


        <EditText

            android:id="@+id/editText1"

            android:layout_width="fill_parent"

            android:layout_height="wrap_content"

            android:layout_alignParentTop="true"

            android:layout_marginTop="32dp"

            android:hint="Enter your text"

            android:ems="10" >

            <requestFocus />

        </EditText>


<Button

            android:id="@+id/button1"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_alignLeft="@+id/editText1"

            android:layout_alignRight="@+id/editText1"

            android:layout_below="@+id/editText1"

            android:text="Display" /> 


</LinearLayout> 




MainActivity.java


package com.example.anonymous.studioedittext;


import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.Toast;


public class MainActivity extends AppCompatActivity {


    EditText userInput;

    Button displayInput;


    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);


        userInput = (EditText) findViewById(R.id.editText1);

        displayInput = (Button) findViewById(R.id.button1);


        displayInput.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                Toast.makeText(getApplicationContext(), userInput.getText(), Toast.LENGTH_SHORT).show();

            }

        });

    }




[출처] http://www.androidcodec.com/android-studio-edittext-example/



반응형

댓글()

EditText 입력값 다른 Activity 에서 출력하기

반응형

다른곳도 수정해야 하지만 파란색도 빠트리지 말고 수정해줍니다.


Code for MainActivity.java file.

package com.passedittextvalue_android_examples.com;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity {

 EditText SendValue;
 Button SendEditTextValue;
 Intent intent;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 
 SendEditTextValue = (Button)findViewById(R.id.button1);
 SendValue = (EditText)findViewById(R.id.editText1);
 
 SendEditTextValue.setOnClickListener(new View.OnClickListener() {
 
 @Override
 public void onClick(View v) {
 
 intent = new Intent(getApplicationContext(),SecondActivity.class);
 intent.putExtra("EdiTtEXTvALUE", SendValue.getText().toString());
 startActivity(intent);
 
 }
 });
 }
}

Code for activity_main.xml layout file.

<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"
 tools:context="com.passedittextvalue_android_examples.com.MainActivity" >

 <EditText
 android:id="@+id/editText1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_centerHorizontal="true"
 android:layout_centerVertical="true"
 android:ems="10" >
 </EditText>

 <Button
 android:id="@+id/button1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_below="@+id/editText1"
 android:layout_centerHorizontal="true"
 android:layout_marginTop="26dp"
 android:text="Click Here to Pass edittext value to another activity in android" />

 <TextView
 android:id="@+id/textView1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_alignParentTop="true"
 android:layout_centerHorizontal="true"
 android:text="Main Activity"
 android:textAppearance="?android:attr/textAppearanceLarge" />

</RelativeLayout>

 

Code for SecondActivity.java file.

package com.passedittextvalue_android_examples.com;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class SecondActivity extends Activity {

 TextView receive;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_second);
 
 receive = (TextView)findViewById(R.id.textView1);
 
 receive.setText(getIntent().getStringExtra("EdiTtEXTvALUE"));
 
 }
}

Code for activity_second.xml layout file.

 <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" tools:context="com.passedittextvalue_android_examples.com.SecondActivity" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="22dp" android:text="Second Activity" android:textAppearance="?android:attr/textAppearanceLarge" /> </RelativeLayout>

Screenshot:

Pass EditText value to another activity in android



Click Here to download Pass EditText value to another activity in android project.


[출처] https://www.android-examples.com/pass-edittext-value-to-another-activity-in-android/


반응형

댓글()

Android 개발환경 구성 (ver 2018-03-21)

프로그래밍/Android (Java)|2018. 3. 21. 17:03
반응형
1. Android 개발 환경 구축

작업PC에 Android 개발 환경을 구축해야 합니다.


1) Java SE 설치

위 URL에서 JDK 10 버전이 나왔으므로 다운받아 설치합니다.

* 명령프롬프트에서 java 명령어가 실행된다고 해도 아래 '시스템변수'를 반드시 설정해주어야 합니다.

설치후 '컴퓨터' 아이콘 우클릭 > 속성 > 고급의 '시스템변수' 에 추가
변수명 : JAVA_HOME / 값 : C:\Program Files\Java\jdk-10
변수명 : JRE_HOME / 값 : C:\Program Files\Java\jre-10
변수명 : Path (추가 ) / 값 : ;C:\Program Files\Java\jdk-10\bin    // 앞에 세미콜론으로 구분하는것 주의

설정 저장 후 리부팅 해주면 적용 됩니다.


2) Android SDK 설치

아래 URL에서 'Android Studio' 를 다운로드 받아 설치합니다.

https://developer.android.com/studio/index.html?hl=ko

'명령줄 도구만 다운로드' 는 받을 필요가 없습니다.

설치 후 실행하면 초기 화면에서 'SDK Manager' 를 구동할 수 있는 화면이 나옵니다.
선택하지 못하고 기본값으로 구동 후 Android Studio 작업 화면으로 들어왔다면
우측 상단에 '안드로이드 다운로드' 표시의 'SDK Manager' 아이콘을 눌러 실행시킬 수 있습니다.

< 설치해야할 패키지 >
[SDK Platforms] 탭에서 원하는 버전의 API Level 을 선택합니다. (다중 선택 가능)

* 참고로 제가 자주 쓰는 버전이 'Android 5.1 (Lollipop) / API Level 22' 입니다.

[SDK Tools] 탭에서 아래 요소 선택합니다.
- Android SDK Build-Tools 28-rc1    // 가장 최신 버전 하나만 설치하면 됩니다.
- Android SDK Platform-Tools
- Android SDK Tools
그외 선택되어진것은 그냥 두고 [OK] 를 눌러 설치를 진행합니다.
설치 과정 중 동의를 얻는 부분이 있으니 체크하고 넘어갑니다.
설치가 다 되었으면 Android Studio 창을 닫습니다.





3. Tomcat, ANT 설치 (서버 구축 - JSP)


위 URL에서 다운받아 설치 (생략)
* 둘다 다운받아 압축풀고 적당한 디렉토리에 넣은후에 각 프로그램의 bin 디렉토리를 PATH 설정만 해주면 됩니다.

그리고 작업PC에서도 ant 를 설치 합니다.

압축을 풀고 적당한 디렉토리로 옮기고 아래처럼 윈도우 환경변수를 추가해줍니다.

변수명 : ANT_HOME / 값 : C:\apache-ant-1.9.4
변수명 : TOMCAT_HOME / 값 : C:\apache-tomcat-7.0.55\bin    // 작업PC에서 파일 한개 생성후 서버로 복사할 작업이 있는데
                                                                                                                            그 서버가 리눅스 서버이면 작업PC에 tomcat 설치 안해도 됩니다.


4. Client APP (.apk) 생성

gcm-demo-client 샘플 파일을 이용해 apk 파일을 생성해봅니다.

아래 파일을 수정합니다.
C:\spring\android-sdks\extras\google\gcm\samples\gcm-demo-client\src\com\google\android\gcm\demo\app\CommonUtilities.java

static final String SERVER_URL = "http://neulwon.com/gcm-demo";    // 서버 주소 및 샘플 디렉토리 (포트사용시 도메인뒤에 :8080 와 같이 추가)
static final String SENDER_ID = "831858421523";    // Project ID

명령 프롬프트 창을 열어 아래와 같이 명령을 내립니다.

cd c:\spring\android-sdks\extras\google\gcm\samples\gcm-demo-client

c:\spring\android-sdks\tools\android.bat update project --name GCM -p . --target android-16

여기서 마지막줄에 'please use the --subprojects parameter.' 라는 메세지가 출력되면 위 project 뒤에 --subprojects 를 붙여 실행하면 됩니다.

c:\apache-ant-1.9.4\bin\ant clean debug

그러면 apk 파일이 하나 생기는데 이것을 스마트폰으로 옮겨 설치합니다.
c:\spring\android-sdks\extras\google\gcm\samples\gcm-demo-client\bin\GCM-debug.apk

실행을 하면 위 구축해놓은 서버로 스마트폰 단말기 장치 regId 값을 넘겨주고,
서버 웹페이지에서 1개 장치 등록된것이 확인됩니다.
나타나는 버튼을 통해 스마트폰으로 GCM을 전송해볼 수 있습니다.


반응형

댓글()

안드로이드 음성 인식 기능 (STT)

프로그래밍/Android (Java)|2017. 10. 10. 17:37
반응형

In this tutorial we are going to show how to use Android’s Speech To Text API. Android currently supports offline mode also. The only thing is that you have to downlad offline language packages.

To learn how to enable offline mode speech to text, please follow the tutorial How to enable offline Speech To Text in Android

See following Steps :

  1. Start RecognizerIntent intent with the RecognizerIntent.ACTION_RECOGNIZE_SPEECH as action.
  2. Handle the text data returned by Speech to Text API

1. Manifest file

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
    package="com.stackandroid.speechtotext"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="19"
        android:targetSdkVersion="21" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

2. Activity layout file

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:background="@color/bg_color"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/txt_output"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="100dp"
        android:textColor="@color/white"
        android:textSize="26dp"
        android:textStyle="normal" />
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="60dp"
        android:gravity="center"
        android:orientation="vertical" >
        <ImageButton
            android:id="@+id/btn_mic"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:background="@null"
            android:scaleType="centerCrop"
            android:src="@drawable/microphone" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:text="Speech to text using Google API"
            android:textColor="@color/white"
            android:textSize="15dp"
            android:textStyle="normal" />
    </LinearLayout>
</RelativeLayout>

3. Main Activity code

Start the speech recognizer intent using startActivityForResult() with bundle extras.

Required extras:

Optional extras:

Result extras (returned in the result, not to be specified in the request):

Note: The extra EXTRA_LANGUAGE_MODEL is mandatory. Also handle ActivityNotFoundException there may be no applications installed in the device to support this speech recognition action.

MainActivity.java
package com.stackandroid.speechtotext;
import java.util.ArrayList;
import java.util.Locale;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
    private final int SPEECH_RECOGNITION_CODE = 1;
    private TextView txtOutput;
    private ImageButton btnMicrophone;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        txtOutput = (TextView) findViewById(R.id.txt_output);
        btnMicrophone = (ImageButton) findViewById(R.id.btn_mic);
        btnMicrophone.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startSpeechToText();
            }
        });
    }
    /**
     * Start speech to text intent. This opens up Google Speech Recognition API dialog box to listen the speech input.
     * */
     private void startSpeechToText() {
        Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
                RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
        intent.putExtra(RecognizerIntent.EXTRA_PROMPT,
                "Speak something...");
        try {
            startActivityForResult(intent, SPEECH_RECOGNITION_CODE);
        } catch (ActivityNotFoundException a) {
            Toast.makeText(getApplicationContext(),
                    "Sorry! Speech recognition is not supported in this device.",
                    Toast.LENGTH_SHORT).show();
        }
     }
     /**
      * Callback for speech recognition activity
      * */
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
         switch (requestCode) {
         case SPEECH_RECOGNITION_CODE: {
             if (resultCode == RESULT_OK && null != data) {
                 ArrayList<String> result = data
                         .getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
                 String text = result.get(0);
                 txtOutput.setText(text);
             }
             break;
         }
         }
     }
}

4. Demonstration
Speech to text demonstration using RecognizerIntent .

Speech to text demo
Speech to text demo

Offline mode is not enabled

Offline mode not enabled
Offline mode not enabled




[출처] http://stackandroid.com/tutorial/android-speech-to-text-tutorial/

반응형

댓글()

웹서버를 통한 파일 자동 업데이트

프로그래밍/Android (Java)|2017. 9. 27. 09:11
반응형

아래 내용은 안드로이드 6.x 까지만 적용되는 예제입니다.

안드로이드 7.x 부터는 다른 예제를 찾아보세요! ㅜ.ㅜ

참고 : http://duongame.tistory.com/263 (Android 7.0 APK 파일 설치)

 

 

 

웹서버 설정

 

1. 파일명 : application.properties

 

#messages for udpate
versionCode=9
versionName=1.1
fileName=TraMainActivity.apk
message=\ufffd\ufffd\u022d\ufffd\ufffd\ufffd\ufffd\u05f9\u6e6e\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd \ufffd\ufffd\ufffd\ufffd \ufffd\u05b5\ufffd\ufffd\ufffd \ufffd\ufffd\ufffd\ufffd\ufffd\u03ff\ufffd\ufffd\ufffd\ufffd\u03f4\ufffd. \ufffd\ufffd\u022d\ufffd\ufffd \ufffd\ufffd\ufffd\ufffd\ufffd\ufffd \ufffd\ufffd\ufffd\ufffd\ufffd\u05b5\ufffd\ufffd\ufffd \ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u0534\u03f4\ufffd.
title=\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u01ae\ufffd\ufffd \ufffd\ufffd\ufffd\ufffd\ufffd\u0574\u03f4\ufffd.

 

message 에서 줄바꿈 하려면 한줄로 적되, 개행할 곳에 \r\n 를 사용하면 된다.

 

2. 원문파일명 : application.properties.source.txt

 

#messages for udpate
versionCode=2
versionName=1.12
fileName=TraMainActivity.apk
message=통화견적및방문견적을 볼수 있도록 수정하였습니다. 정화조 도면을 볼수있도록 수정중입니다.
title=업데이트를 시작합니다. 

 

기존에 설치된 app 의 AndroidManifest.xml 과 웹서버에 있는 application.properties 의 versionCode 를 비교해서

웹서버 versionCode 값이 더 클 경우 앱에서 팝업으로 알려주게 된다. (최대값이 

2147483647

 이다.)

versionName 은 필요시 사용자에게 보여주기 위한 번호일 뿐이다. (비교 안함)

 

AndroidManifest.xml 파일의 옵션값이 먹히지 않을 경우 (AndroidStudio를 사용할 경우) build.gradle (Module: app) 내의 옵션이 우선되기 때문이다.

 

3. 파일 형식 변환

 

원문 파일을 jdk 폴더 내의 bin폴더에 있는 native2ascii.exe 명령으로 바꾼것이다.

 

native2ascii.exe application.properties.source.txt application.properties

 

[사용 방법]

-- versionCode 와 앱의 manifest 파일의 versionCode와 일치시키면 된다. versionName도 마찬가지로 일치시키면 된다.

-- fileName은 앱의 파일 이름을 적어주면된다.

-- message에는 업데이트 된 내용을 적어주면 된다.

-- title은 다운로드 받는 progress dialog의 제목이다.

 

설정 파일 작성을 완료 했다면 설정 파일과 앱파일을 서버상에 같은 폴더에 업로드 한다.

아래 소스에서는 웹서버의 /download/ 디렉토리에 업로드 하도록 하였다.

 

 

 

필수 권한

 

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

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

 

 

 

AutoupdateActivity.java

package com.neulwon.study;


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;




public class AutoupdateActivity extends Activity {


    //새버전의 프로그램이 존재하는지 여부
    private int newver=0;
    private int oldver=0;
    private String strVer;
    
    private String fileName;
    private CharSequence updateMessage;
    private String updateTitle; 
    
    // Progress Dialog 
    private TextView textVersion;
    
    private TextView progressTitle;
    private TextView progressText;
    private ProgressBar progressBar;
    private RelativeLayout downloadUpdateLayout;
    
    //확인하고 싶은 패키지명 String
    private static final String CHECK_PACKAGE_NAME="com.neulwon.study";


    public static final String MSG_TAG = "AutoupdateActivity";
    
    private static final String IP_ADDRESS = "sysdocu.tistory.com";


    // Update Url
    private static final String APPLICATION_PROPERTIES_URL = "http://" + IP_ADDRESS + "/download/application.properties";
    private static final String APPLICATION_DOWNLOAD_URL = "http://" + IP_ADDRESS + "/download/";


    public static final int MESSAGE_DOWNLOAD_STARTING = 3;
    public static final int MESSAGE_DOWNLOAD_PROGRESS = 4;
    public static final int MESSAGE_DOWNLOAD_COMPLETE = 5; 
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_autoupdate);
     
        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        progressText = (TextView) findViewById(R.id.progressText);
        progressTitle = (TextView) findViewById(R.id.progressTitle);
        downloadUpdateLayout = (RelativeLayout) findViewById(R.id.layoutDownloadUpdate);
        
        textVersion = (TextView) findViewById(R.id.textVersion );
        
// 앱실행시 기존 다운로드 파일 삭제
String del_localpath = getDownloadDirectory();
File del_file = new File(del_localpath + "/update-debug.apk");
        del_file.delete();


        // 업데이트 체크
        checkForUpdate();
        
        PackageInfo oldversionInfo;
        try {
            oldversionInfo = getPackageManager().getPackageInfo(CHECK_PACKAGE_NAME,PackageManager.GET_META_DATA);       
            strVer = oldversionInfo.versionName;
        } catch (NameNotFoundException e1) {
            e1.printStackTrace();
        }        
           
        //textVersion.setText( "버전 " + strVer );
textVersion.setText( "IPTV 업데이트" );
    }
   
    //앱 업데이트 검사
    public void checkForUpdate() {           
      new Thread(new Runnable(){
          public void run(){
              Looper.prepare();   
              
              // 서버상의 Properties 얻기
              Properties updateProperties = queryForProperty(APPLICATION_PROPERTIES_URL);
              String verName;
              
              if ( updateProperties != null && updateProperties.containsKey("versionCode") ) {
                
                  int newversion = Integer.parseInt(updateProperties.getProperty("versionCode"));
                  //int installedVersion = TetherApplication.this.getVersionNumber();
                  fileName = updateProperties.getProperty("fileName", "");
                  updateMessage = updateProperties.getProperty("message", "");
                  updateTitle = updateProperties.getProperty("title", "업데이트가 가능합니다.");
                  verName = updateProperties.getProperty("versionName", "");
                  
                  newver = newversion;
                  
                  try {
                      //설치된 앱 정보 얻기
                      PackageInfo oldversionInfo = getPackageManager().getPackageInfo(CHECK_PACKAGE_NAME,PackageManager.GET_META_DATA);
                      oldver = Integer.valueOf(oldversionInfo.versionCode);
                      
                      //다운로드 폴더 얻어오기
                      String localpath = getDownloadDirectory();


                      Log.d("앱버전","앱버전 : " + oldver );
                      Log.d("서버상","서버에 있는 파일 버전 : " + newver );
                      Log.d("받아온경로","받아온 경로: " + localpath);


                      if ( oldver < newver ) {    //파일 버전비교                            
                          openUpdateDialog( APPLICATION_DOWNLOAD_URL + fileName , fileName , updateMessage , updateTitle,localpath);                
                      } else {
                          Log.d(MSG_TAG, " 최신버전입니다. 버전 : " + verName );
                      }
                      //textVersion.setText(" Ver : " + verName);
                  } catch ( Exception e ) {
                      e.printStackTrace();
                  }
              }
              Looper.loop();
          }
      }).start();
    }
   
    //다운로드 폴더 얻기
    private String getDownloadDirectory(){
        String sdcardPath="";
        String downloadpath = "";
        if ( isUsableSDCard(true)){    //외장메모리 사용가능할 경우
            sdcardPath = Environment.getExternalStorageDirectory().getPath();
            //downloadpath = sdcardPath + "/download/";
downloadpath = sdcardPath + "/data/local/tmp/";
        } else {                       //내장메모리 위치
            File file = Environment.getRootDirectory();
            sdcardPath = file.getAbsolutePath();
            //downloadpath = sdcardPath + "/download";
downloadpath = sdcardPath + "/data/local/tmp";
        }
    return downloadpath;
    }
    
    //외장메모리 사용 가능여부 확인   
    private boolean isUsableSDCard(boolean requireWriteAccess) {
        String state = Environment.getExternalStorageState();
        if ( Environment.MEDIA_MOUNTED.equals(state)) {
            return true;
        } else if( !requireWriteAccess &&
               Environment.MEDIA_MOUNTED_READ_ONLY.equals(state) ) {
           return true;
        }
        return false;
    }    
    
    
    //서버의 application.properties 파일 읽어오기
    public Properties queryForProperty(String url) {
        Properties properties = null;
        
        HttpClient client  = new DefaultHttpClient();
        HttpGet request = new HttpGet(String.format(url));
       
        try {
            HttpResponse response = client.execute(request);            
            StatusLine status = response.getStatusLine();
            
            if ( status.getStatusCode() == 200 ) {
                HttpEntity entity = response.getEntity();
                properties = new Properties();
                properties.load(entity.getContent());
            }
        } catch ( IOException e ) {
            Log.d("오류","Can't get property '" + url + "'.");
        }
        return properties;
    }
    
    //업데이트 할 것인지 확인
    public void openUpdateDialog(final String downloadFileUrl, final String fileName,
          final CharSequence message, final String updateTitle,final String localpath4down) {
      
        LayoutInflater li = LayoutInflater.from(this);
        Builder dialog;
        View view;
      
        view = li.inflate(R.layout.updateview, null);
        TextView messageView = (TextView) view.findViewById(R.id.updateMessage);
        TextView updateNowText = (TextView) view.findViewById(R.id.updateNowText);
      
        if (fileName.length() == 0)  // No filename, hide 'download now?' string              
            updateNowText.setVisibility(View.GONE);
       
        messageView.setText(message);                 
      
        dialog = new AlertDialog.Builder(AutoupdateActivity.this)
                               .setTitle(updateTitle)
                               .setView(view);
           
        if (fileName.length() > 0) {
            //dialog.setNeutralButton("취소", new DialogInterface.OnClickListener() {
            //    public void onClick(DialogInterface dialog, int whichButton) {
            //        Log.d(MSG_TAG, "No pressed");
            //    }
            //});
            dialog.setNegativeButton("확인", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                    Log.d(MSG_TAG, "Yes pressed");
                    Log.d("경로명","경로명 : " + downloadFileUrl + " 파일명 : " + fileName );
                    downloadUpdate(downloadFileUrl, fileName, localpath4down);
                }
            });          
        } else {              
            dialog.setNeutralButton("확인",new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                    Log.d(MSG_TAG, "Ok pressed");
                }
            });
        }
        dialog.show();
//dialog.setCancelable(false); // back 키 무효. 동작 안함
        //dialog.setCanceledOnTouchOutside(false); // dialog 바깥 클릭 무효. 동작 안함

    
    //다운로드 받은 앱을 설치, 이전 실행 앱 종료
    public void downloadUpdate(final String downloadFileUrl, final String fileName,final String localpath) {
        new Thread(new Runnable(){
            public void run(){
                Message msg = Message.obtain();
                msg.what = MESSAGE_DOWNLOAD_STARTING;
                msg.obj = localpath + fileName ;
              
                File apkFile = new File ( localpath + fileName );
                Log.d("downloadUpdate","경로1:"+ localpath + fileName  );
                viewUpdateHandler.sendMessage(msg);
              
                downloadUpdateFile(downloadFileUrl, fileName, localpath);              
              
                //다운로드 받은 패키지를 인스톨한다.
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setDataAndType(Uri.fromFile(apkFile),"application/vnd.android.package-archive");
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);


               /*
               * 안드로이드 프로세스는  단지 finish() 만 호출 하면 죽지 않는다.
               * 만약 프로세스를 강제로 Kill 하기위해서는 화면에 떠있는 Activity를 BackGround로 보내고
               * 강제로 Kill하면 프로세스가  완전히 종료가 된다.
               * 종료 방법에 대한 Source는 아래 부분을 참조 하면 될것 같다.
               */
                moveTaskToBack(true);
                finish();
                android.os.Process.sendSignal(android.os.Process.myPid(), android.os.Process.SIGNAL_KILL);
          }
        }).start();
       }
      
    public Handler viewUpdateHandler = new Handler(){
        public void handleMessage(Message msg) {
            switch(msg.what) {
                case MESSAGE_DOWNLOAD_STARTING :
                    Log.d(MSG_TAG, "프로그레스바 시작");
                    progressBar.setIndeterminate(true);
                    progressTitle.setText((String)msg.obj + " 다운로드");
                    progressText.setText("시작중...");
                    downloadUpdateLayout.setVisibility(View.VISIBLE);
                    break;
                case MESSAGE_DOWNLOAD_PROGRESS :
                    progressBar.setIndeterminate(false);
                    progressText.setText(msg.arg1 + "k /" + msg.arg2 + "k");
                    progressTitle.setText("최신 버전을 다운로드 하고 있습니다.");
                    progressBar.setProgress(msg.arg1*100/msg.arg2);
                    break;
                case MESSAGE_DOWNLOAD_COMPLETE :
                    Log.d(MSG_TAG, "다운로드 완료.");
                    progressText.setText("");
                    progressTitle.setText("");
                    downloadUpdateLayout.setVisibility(View.GONE);
                    break;              
            }
            super.handleMessage(msg);
        }
    };
     
    public boolean downloadUpdateFile(String downloadFileUrl, String destinationFilename, String localPath) {
        if (Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED) == false) {
            return false;
        }
      
        File downloadDir = new File( localPath );
        Log.d("DOWNLOAD","다운로드중");
        if (downloadDir.exists() == false) {
            downloadDir.mkdirs();
        } else {
            File downloadFile = new File( localPath + destinationFilename );
            if (downloadFile.exists()) {
                downloadFile.delete();
            }
        }
        return this.downloadFile(downloadFileUrl, localPath, destinationFilename );
    }    
    
    //파일 다운로드 과정 표시
    public boolean downloadFile(String url, String destinationDirectory, String destinationFilename ) {
        boolean filedownloaded = true;
        HttpClient client = new DefaultHttpClient();
        HttpGet request = new HttpGet(String.format(url));
        Message msg = Message.obtain();
        
        try {
            HttpResponse response = client.execute(request);
            StatusLine status = response.getStatusLine();
            Log.d(MSG_TAG, "Request returned status " + status);
               
            if (status.getStatusCode() == 200) {
                HttpEntity entity = response.getEntity();
                InputStream instream = entity.getContent();
                int fileSize = (int)entity.getContentLength();
                FileOutputStream out = new FileOutputStream(new File(destinationDirectory + destinationFilename));
                byte buf[] = new byte[8192];
                int len;
                int totalRead = 0;


                while((len = instream.read(buf)) > 0) {
                    msg = Message.obtain();
                    msg.what = MESSAGE_DOWNLOAD_PROGRESS;
                    totalRead += len;
                    msg.arg1 = totalRead / 1024;
                    msg.arg2 = fileSize / 1024;
                    viewUpdateHandler.sendMessage(msg);
                    out.write(buf,0,len);
                }
                   out.close();
            } else {
                throw new IOException();
            }
        } catch (IOException e) {  
            filedownloaded = false;
        }
        msg = Message.obtain();
        msg.what = MESSAGE_DOWNLOAD_COMPLETE;
        viewUpdateHandler.sendMessage(msg);
        return filedownloaded;
    }  


}

 

 

 

activity_autoupdate.xml

 

<FrameLayout 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:layout_gravity="center" >
    <TextView        android:id="@+id/textVersion"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_gravity="center"        android:text="Version"        android:textSize="14sp" />
    <LinearLayout        android:layout_width="wrap_content"        android:layout_height="wrap_content" android:layout_gravity="center_vertical">                <RelativeLayout android:id="@+id/layoutDownloadUpdate"            android:layout_width="match_parent"            android:layout_height="60dp"            android:visibility="gone"            android:layout_gravity="center_horizontal"            android:gravity="center"            android:background="#A0909090">
            <TextView                android:id="@+id/progressTitle"                android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:layout_alignParentTop="true"                android:paddingLeft="5dp"                android:paddingRight="5dp"                android:text=""                android:textStyle="bold"                android:textColor="#000000" />
            <ProgressBar                android:id="@+id/progressBar"                android:layout_width="match_parent"                android:layout_height="wrap_content"                style="?android:attr/progressBarStyleHorizontal"                android:paddingTop="22dp"                android:paddingLeft="5dp"                android:paddingRight="5dp"                android:layout_alignParentTop="true"                android:max="100" />
            <TextView                  android:id="@+id/progressText"                android:layout_width="match_parent"                android:layout_height="wrap_content"                 android:paddingTop="40dp"                android:paddingLeft="5dp"                android:paddingRight="5dp"                android:layout_alignParentTop="true"                android:text=""                android:textStyle="bold"                android:textColor="#000000" />
        </RelativeLayout>
    </LinearLayout>  
</FrameLayout>

 

 

 

updateview.xml (dialog 창)

 

<ScrollView     xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent" >         <LinearLayout        android:orientation="vertical"        android:layout_width="match_parent"        android:layout_height="wrap_content">
      <TextView              android:id="@+id/updateMessage"              android:layout_width="match_parent"              android:layout_height="match_parent"              android:autoLink="web"              android:paddingLeft="15dp"              android:paddingRight="15dp"              android:paddingTop="15dp"              android:text=""              android:textColor="#00ffff"              android:textStyle="bold" />       <TextView               android:text="Update"               android:id="@+id/updateNowText"               android:layout_width="match_parent"                android:layout_height="wrap_content"               android:paddingTop="15dp"               android:paddingLeft="15dp"               android:paddingRight="15dp"               android:textStyle="bold"               android:textColor="#000000" />  
    </LinearLayout>
</ScrollView>

 

 

[출처] http://blog.daum.net/wonky12/1401710

 

반응형

댓글()

네비게이션바 (navigation bar) 상태 확인

프로그래밍/Android (Java)|2017. 9. 14. 13:39
반응형

import android.view.KeyEvent;

import android.view.KeyCharacterMap;



boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);

boolean hasHomeKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME);


if (hasBackKey && hasHomeKey) {

    // no navigation bar, unless it is enabled in the settings

} else {

    // 99% sure there's a navigation bar

}



[출처] https://stackoverflow.com/questions/16092431/check-for-navigation-bar

반응형

댓글()

웹페이지 텍스트 내용 가져와서 출력하기

프로그래밍/Android (Java)|2017. 5. 22. 08:53
반응형

import java.io.BufferedReader;

import android.os.StrictMode;

import java.io.InputStreamReader;

import android.widget.EditText;

import java.net.URL;

import java.io.IOException;
 
 

아래 코드는 onCreate 안에 넣는다.

 

    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();

    StrictMode.setThreadPolicy(policy);

  

    TextView display = (TextView)findViewById(R.id.display);

 

    StringBuffer sb = new StringBuffer();

    try {

        URL url = new URL("https://sysdocu.tistory.com/check_version.txt");

        BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));

        String str = null;

        while((str = reader.readLine()) != null){

           sb.append(str);

        }

        display.setText(sb.toString());

    } catch (IOException e) {

        e.printStackTrace();

    }

 

 

레이아웃 파일에는 아래 내용 삽입

 

    <TextView

        android:id="@+id/display"

        android:layout_width="match_parent"

        android:layout_height="wrap_content" />

 

 

* 주의 : Android 9 이상에서는 보안요소가 추가되어서 인지 모르겠지만

URL 이 https 이어야 동작을 합니다. (http 사용 불가)

반응형

댓글()

지연 실행 (delay 그리고 재호출시 연기하기)

프로그래밍/Android (Java)|2016. 12. 14. 09:53
반응형

import android.os.Handler;



public class TVActivity extends Activity { 여기 안에다가 아래 내용을 미리 선언합니다.


    Runnable myRunnable = new Runnable() {

        @Override

        public void run() {

            final ImageView imgNumber = (ImageView) findViewById(R.id.getImage);

            imgNumber.setVisibility(View.GONE);

        }

    };

    Handler myHandler = new Handler();



나중에 클릭리스너나 키이벤트에 아래 내용 추가해서 불러오면 됩니다.


    myHandler.removeCallbacks(myRunnable);       // 반복해서 누를경우 기존 딜레이 취소

    myHandler.postDelayed(myRunnable, 5000);    // 딜레이 호출 (5초뒤 실행)



혹시 안될경우 {, } 밖으로 또는 안으로 이동하며 테스트 해볼것. 위치가 중요합니다.


반응형

댓글()