android activity, service 에서 서로 데이터를 주고 받는 예제 입니다.

참고 url

https://bitbucket.org/alexfu/androidserviceexample/src


간단하게 서비스를 시작할때

bindService를 통해 내가 만든 Messenger를 서비스로 던져 놓고 데이터를 받는 방식입니다.


작업 내용 - MainActivity.java

public class MainActivity extends AppCompatActivity {

	private Messenger mServiceMessenger = null;
	private boolean mIsBound;

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

		Button send = (Button) findViewById(R.id.send);
		send.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				// 메시지를 서비스로 전달
				sendMessageToService("from main");
			}
		});
		
		// 서비스 시작
		setStartService();
	}
	
	/** 서비스 시작 및 Messenger 전달 */
	private void setStartService() {
        startService(new Intent(MainActivity.this, ControlService.class));
        bindService(new Intent(this, ControlService.class), mConnection, Context.BIND_AUTO_CREATE);
        mIsBound = true;
    }
    
    /** 서비스 정지 */
    private void setStopService() {
	    if (mIsBound) {
            unbindService(mConnection);
            mIsBound = false;
        }
        stopService(new Intent(MainActivity.this, ControlService.class));
    }
    
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Log.d("test","onServiceConnected");
            mServiceMessenger = new Messenger(iBinder);
            try {
                Message msg = Message.obtain(null, ControlService.MSG_REGISTER_CLIENT);
                msg.replyTo = mMessenger;
                mServiceMessenger.send(msg);
            }
            catch (RemoteException e) {
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
        }
    };
    
    /** Service 로 부터 message를 받음 */
    private final Messenger mMessenger = new Messenger(new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            Log.i("test","act : what "+msg.what);
            switch (msg.what) {
                case ControlService.MSG_SEND_TO_ACTIVITY:
                    int value1 = msg.getData().getInt("fromService");
                    String value2 = msg.getData().getString("test");
                    Log.i("test","act : value1 "+value1);
                    Log.i("test","act : value2 "+value2);
                    break;
            }
            return false;
        }
    }));
    
    /** Service 로 메시지를 보냄 */
    private void sendMessageToService(String str) {
        if (mIsBound) {
            if (mServiceMessenger != null) {
                try {
                    Message msg = Message.obtain(null, ControlService.MSG_SEND_TO_SERVICE, str);
                    msg.replyTo = mMessenger;
                    mServiceMessenger.send(msg);
                } catch (RemoteException e) {
                }
            }
        }
    }
}


ControlService.java

public class ControlService extends Service {

	public static final int MSG_REGISTER_CLIENT = 1;
	//public static final int MSG_UNREGISTER_CLIENT = 2;
	public static final int MSG_SEND_TO_SERVICE = 3;
	public static final int MSG_SEND_TO_ACTIVITY = 4;
	
	private Messenger mClient = null;	// Activity 에서 가져온 Messenger

	@Override
	public void onCreate() {
		super.onCreate();
		
		Button send_service = (Button) mView.findViewById(R.id.send_service);
		send_service.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				sendMsgToActivity(1234);
			}
		});
	}

	@Override
	public IBinder onBind(Intent intent) {
		return mMessenger.getBinder();
	}
	
	/** activity로부터 binding 된 Messenger */
	private final Messenger mMessenger = new Messenger(new Handler(new Handler.Callback() {
		@Override
		public boolean handleMessage(Message msg) {
			Log.w("test","ControlService - message what : "+msg.what +" , msg.obj "+ msg.obj);
			switch (msg.what) {
				case MSG_REGISTER_CLIENT:
					mClient = msg.replyTo;	// activity로부터 가져온 
					break;
			}
			return false;
		}
	}));
	
	private void sendMsgToActivity(int sendValue) {
		try {
			Bundle bundle = new Bundle();
			bundle.putInt("fromService", sendValue);
			bundle.putString("test","abcdefg");
			Message msg = Message.obtain(null, MSG_SEND_TO_ACTIVITY);
			msg.setData(bundle);
			mClient.send(msg);		// msg 보내기
		} catch (RemoteException e) {
		}
	}
}

결과화면

각각 버튼을 눌러 messenger를 통해 메시지를 주고 받았습니다.


오늘은 최상단 위치에  Services를 통해 View를 실행하는 예제를 작성하겠습니다.

먼저 Service에서 WindowManager를 통해 View를 만들 수 있습니다.


코드 작성

AndroidManifest.xml (permission 과 application 영역내의 service를 등록 해 줍니다.)

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

<application>

	...
	
	<service
		android:name=".MyService"
		android:enabled="true"
		android:permission="android.permission.SYSTEM_ALERT_WINDOW" >
	</service>
</application>


view_in_service.xml (서비스를 통해 보여질 view xml을 작성합니다.)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:background="#0000ff">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:textColor="#ffffff"
        android:id="@+id/textView" />

    <ImageButton
        android:layout_width="368dp"
        android:layout_height="wrap_content"
        android:id="@+id/bt"
        android:text="click"
        android:textColor="#ffffff"
        android:src="@mipmap/ic_launcher"
        android:layout_below="@+id/textView"
        android:layout_alignParentLeft="true"
        android:layout_marginTop="12dp" />

</RelativeLayout>


MyService.java

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.TextView;

public class MyService extends Service {

	WindowManager wm;
	View mView;

	@Override
	public IBinder onBind(Intent intent) { return null; }
	
	@Override
	public void onCreate() {
		super.onCreate();
		LayoutInflater inflate = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		wm = (WindowManager) getSystemService(WINDOW_SERVICE);

		WindowManager.LayoutParams params = new WindowManager.LayoutParams(
				/*ViewGroup.LayoutParams.MATCH_PARENT*/300,
				ViewGroup.LayoutParams.WRAP_CONTENT,
				WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
				WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
						|WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
						|WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
				PixelFormat.TRANSLUCENT);

		params.gravity = Gravity.LEFT | Gravity.TOP;
		mView = inflate.inflate(R.layout.view_in_service, null);
		final TextView textView = (TextView) mView.findViewById(R.id.textView);
		final ImageButton bt =  (ImageButton) mView.findViewById(R.id.bt);
		bt.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				bt.setImageResource(R.mipmap.ic_launcher_round);
				textView.setText("on click!!");
			}
		});
		wm.addView(mView, params);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		if(wm != null) {
			if(mView != null) {
				wm.removeView(mView);
				mView = null;
			}
			wm = null;
		}
	}
}


MainActivity.java

(마시멜로우 버전 이상부터는 보안이 강화가 되어서 아래 사용자의 동의를 얻어야지만 사용할 수 있습니다.

그래서 checkpermission이라는 부분에서 상세히 작성되어 있습니다.)

public class MainActivity extends AppCompatActivity {

    private static final int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE = 1;

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

        Button bt_start = (Button) findViewById(R.id.bt_start);
        bt_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                checkPermission();
                //startService(new Intent(MainActivity.this, AlwaysOnTopService.class));
            }
        });

        Button bt_stop = (Button) findViewById(R.id.bt_stop);
        bt_stop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                stopService(new Intent(MainActivity.this, MyService.class));
            }
        });
    }

    public void checkPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {   // 마시멜로우 이상일 경우
            if (!Settings.canDrawOverlays(this)) {              // 체크
                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                        Uri.parse("package:" + getPackageName()));
                startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
            } else {
                startService(new Intent(MainActivity.this, MyService.class));
            }
        } else {
            startService(new Intent(MainActivity.this, MyService.class));
        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {
            if (!Settings.canDrawOverlays(this)) {
                // TODO 동의를 얻지 못했을 경우의 처리
                
            } else {
                startService(new Intent(MainActivity.this, MyService.class));
            }
        }
    }
}


완료 및 실행 화면!


   


 



AppCompatSeekBar 를 사용하면 Max값이랑 Progress만 설정 할 수 있게 되어있습니다.

Min이랑 Step 도 되게 해주면 편하게 개발할텐데요.

없으니깐 만들어서 쓰셔야 합니다.


작업 내용

xml 은 아래와 같이 작성하였습니다.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="20dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="15sp"
            android:id="@+id/tv_"
            android:text="SeekBar : "/>

        <android.support.v7.widget.AppCompatSeekBar
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/tv_"
            android:layout_marginTop="20dp"
            android:id="@+id/sb_"/>

    </RelativeLayout>
</android.support.constraint.ConstraintLayout>


.Java code는 아래와 같이 작성하였습니다.

import android.animation.ObjectAnimator;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.AppCompatSeekBar;
import android.view.animation.LinearInterpolator;
import android.widget.SeekBar;
import android.widget.TextView;

import java.text.DecimalFormat;

public class MainActivity extends AppCompatActivity {

    final int max = 5;
    final float min = (float) 0.1;
    final float step = (float) 0.1;
    final String str_title = "SeekBar : ";

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

        final TextView tv_ = (TextView) findViewById(R.id.tv_);
        final AppCompatSeekBar sb_ = (AppCompatSeekBar) findViewById(R.id.sb_);

        setSeekBarMax(sb_, max);
        sb_.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
                setSeekBarChange(progress, tv_);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
        });
        setSeekBarAnimation(sb_);
    }

    private void setSeekBarMax(AppCompatSeekBar sb, int max_value) {
        sb.setMax((int)((max_value-min) / step));
    }

    private void setSeekBarChange(int progress, TextView tv) {
        float value = min + (progress * step);
        DecimalFormat format = new DecimalFormat(".#");
        String str = format.format(value);
        tv.setText(str_title +" ( "+Float.valueOf(str)+" )");
    }

    // 최초 중간 위치 설정
    private void setSeekBarAnimation(AppCompatSeekBar sb) {

        int progress_half = (int)(((max / min) / 2)-1);

        ObjectAnimator animation = ObjectAnimator.ofInt(sb, "progress", progress_half);
        animation.setDuration(100); // 0.5 second
        animation.setInterpolator(new /*DecelerateInterpolator()*/LinearInterpolator());
        animation.start();
    }
}


결과화면

최소 value 0.1 ~ 5.0 사이에 step 은 0.1 만큼씩 움직이게 됩니다.





날씨 : 바람 많이 붐, 미세먼지 없어 보임

체중 : 70.4kg

후기 : 뛰면 갈증이 많이 남, 습도가 높아서 그런지 

땀은 별로 나지 않고, 바람에 맞서서 달려서 힘들긴 힘듬



   


'달리기 흔적' 카테고리의 다른 글

[5km] 2017년 5월 23일  (0) 2017.05.23
[5km] 2017년 5월 16일  (0) 2017.05.16
[5km] 2017년 4월 25일 화요일  (0) 2017.04.25
[5km] 2017년 4월 21일  (0) 2017.04.21
[5km] 2017년 4월 18일  (0) 2017.04.18

앱 링크 URL

https://play.google.com/store/apps/details?id=com.poisonrose.realspeak



  




간단하게 문장을 추가하여, TTS음성으로 영어 문장을 확인할 수 있습니다.


기본적인 데이터를 추가되어 있고, 앞으로도 지속적으로 추가 할 예정입니다.


1. 리스트에서 영어문장을 선택시에 상세보기로 들어가면 속도, 음영 조절을 하며 음성을 확인 할 수 있습니다.


2. 메인 리스트 돋보기를 클릭하면 현재 있는 데이터에서 원하는 문장만 검색이 가능합니다.

(영문, 한글 둘 다 가능)


3. 리스트에서 Play 버튼을 누르면 간단히 음성 재생이 가능합니다.


4. 메인 리스트 우측 + 버튼을 누르시면 내가 원하는 문장을 입력할 수 있습니다.

또한, 내가 입력한 문장은 수정이 가능하게 만들어져 있습니다.


5. 좌측 네비게이션 에서 내가 입력한 문장을 누르면 내가 입력한 문장만 모아서 보입니다.


기타 오류사항이나 문의사항은 메일 주세요

날씨 : 바람 많이 불어서, 땀 별로 많이 나지 않음,

체중 : 70.8kg

후기 : 뛸만함, 목이 많이 탄다거나 힘들진 않았는데, 속도는 여전히 안나옴.

         뛰고 나서도 땀은 아주 조금만 나옴, 바람 많이 붐



  



'달리기 흔적' 카테고리의 다른 글

[5km] 2017년 5월 16일  (0) 2017.05.16
[5km] 2017년 4월 27일 목요일  (0) 2017.04.27
[5km] 2017년 4월 21일  (0) 2017.04.21
[5km] 2017년 4월 18일  (0) 2017.04.18
[10km] 2017년 4월 16일  (0) 2017.04.16

개발을 하다보니 이것저것 외부 라이브러리를 참조하게 되었는데,

프로가드를 적용하다보니 

org.apache.log4j.chainsaw.ControlPanel: can't find superclass or interface javax.swing.JPanel 

천개가 넘는 warning 메시지가 나오면서 빌드가 되지 않았습니다.



그래서 해결책은 간단하게

proguard-rules.pro 파일 내에서 관련 lib에 관한 예외처리를 해주었습니다.

-dontwarn org.apache.log4j.**



안드로이드에서 SQLite like 검색 방법입니다.


SQL Like 검색시 사용 방법

protected Cursor select(String tableName, String col1, String Like) throws SQLiteException{
	return getReadableDatabase().query(tableName, null, col1+ " LIKE ?", new String[] {"%"+ Like+ "%" }, null, null, null, null);
}


SQL Like 검색시 (OR, AND) 사용 방법 (두개 이상의 컬럼시) 

- 당연한 얘기이겠지만, 이렇게 사용하면 성능이 현저히 떨어지기 때문에 권장하지 않습니다.

protected Cursor select(String tableName, String col1, String col2, String Like) throws SQLiteException{
	return getReadableDatabase().query(true, tableName, null, col1+" LIKE '%"+Like+"%' or "+col2+" LIKE '%"+Like+"%'", null, null, null, null, null);
}


TTS 예제 프로그램입니다.

setLanguage() // 지역 선택

setPitch() // 낮거나 높은음을 일정하게 맞춰 주는 옵션

setSpeechRate() // 재생 속도

speak()                // 재생


실행 화면



코드 사용 (xml)

<RelativeLayout
	android:layout_width="match_parent"
	android:layout_height="match_parent">

	<EditText
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:layout_marginTop="20dp"
		android:id="@+id/et"
		android:text="There is something I want to talk to you about."/>

	<Button
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:layout_marginTop="20dp"
		android:layout_below="@+id/et"
		android:text="play"
		android:id="@+id/play"/>

	<RadioGroup
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:id="@+id/rg_local"
		android:layout_marginTop="20dp"
		android:orientation="horizontal"
		android:layout_below="@id/play">

		<RadioButton
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:checked="true"
			android:id="@+id/rb_local1"
			android:text="us"/>

		<RadioButton
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:id="@+id/rb_local2"
			android:text="korea"/>

	</RadioGroup>

	<RadioGroup
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:id="@+id/rg_pitch"
		android:layout_marginTop="20dp"
		android:orientation="horizontal"
		android:layout_below="@id/rg_local">

		<RadioButton
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:checked="true"
			android:id="@+id/rb_pitch1"
			android:text="pitch row"/>

		<RadioButton
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:id="@+id/rb_pitch2"
			android:checked="true"
			android:text="pitch normal"/>

		<RadioButton
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:id="@+id/rb_pitch3"
			android:text="pitch high"/>
	</RadioGroup>

	<RadioGroup
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:id="@+id/rg_rate"
		android:layout_marginTop="20dp"
		android:orientation="horizontal"
		android:layout_below="@id/rg_pitch">

		<RadioButton
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:id="@+id/rb_rate1"
			android:text="x0.1"/>

		<RadioButton
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:id="@+id/rb_rate2"
			android:checked="true"
			android:text="x1"/>

		<RadioButton
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:id="@+id/rb_rate3"
			android:text="x2"/>

		<RadioButton
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:id="@+id/rb_rate4"
			android:text="x3"/>

		<RadioButton
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:id="@+id/rb_rate5"
			android:text="x4"/>
	</RadioGroup>

	<RadioGroup
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:id="@+id/rg_queue"
		android:layout_marginTop="20dp"
		android:orientation="horizontal"
		android:layout_below="@id/rg_rate">

		<RadioButton
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:checked="true"
			android:id="@+id/rb_queue_add"
			android:text="QUEUE_ADD"/>

		<RadioButton
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:id="@+id/rb_queue_flush"
			android:text="QUEUE_FLUSH"/>
	</RadioGroup>
</RelativeLayout>



코드 사용

import android.content.ComponentName;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.support.annotation.IdRes;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioGroup;

import java.util.HashMap;
import java.util.Locale;

public class MainActivity extends AppCompatActivity {

    private TextToSpeech mTts = null;
    private Locale mLocale = Locale.US;
    private float mPitch = (float) 0;
    private float mRate = (float) 0;
    private int mQueue = TextToSpeech.QUEUE_ADD;

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

        final EditText et = (EditText) findViewById(R.id.et);
        Button play = (Button) findViewById(R.id.play);
        play.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(mTts != null) {
                    if(et != null) {
                        String text = et.getText().toString();
                        if(text.length() > 0) {
                            setLanguage(mLocale);
                            setPitch(mPitch);
                            setSpeechRate(mRate);
                            speak(text, 0);
                        }
                    }
                }
            }
        });
        RadioGroup lay_local = (RadioGroup) findViewById(R.id.rg_local);
        RadioGroup lay_pitch = (RadioGroup) findViewById(R.id.rg_pitch);
        RadioGroup lay_rate = (RadioGroup) findViewById(R.id.rg_rate);
        RadioGroup lay_queue = (RadioGroup) findViewById(R.id.rg_queue);
        lay_local.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, @IdRes int id) {
                if(id == R.id.rb_local1) {
                    mLocale = Locale.US;
                } else {
                    mLocale = Locale.KOREA;
                }
            }
        });
        lay_pitch.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, @IdRes int id) {
                if(id == R.id.rb_pitch1) {
                    mPitch = (float) 0.1;
                } else if(id == R.id.rb_pitch2) {
                    mPitch = 1;
                } else if(id == R.id.rb_pitch3) {
                    mPitch = 2;
                }
            }
        });
        lay_rate.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, @IdRes int id) {
                if(id == R.id.rb_rate1) {
                    mRate = (float) 0.1;
                } else if(id == R.id.rb_rate2) {
                    mRate = 1;
                } else if(id == R.id.rb_rate3) {
                    mRate = 2;
                } else if(id == R.id.rb_rate4) {
                    mRate = 3;
                } else if(id == R.id.rb_rate5) {
                    mRate = 4;
                }
            }
        });
        lay_queue.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, @IdRes int id) {
                if(id == R.id.rb_queue_add) {
                    mQueue = TextToSpeech.QUEUE_ADD;
                } else {
                    mQueue = TextToSpeech.QUEUE_FLUSH;
                }
            }
        });
        init();
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mTts != null) {
            if(mTts.isSpeaking()) {
                mTts.stop();
            }
        }
    }

    @Override
    public void onDestroy() {
        if (mTts != null) {
            if(mTts.isSpeaking()) {
                mTts.stop();
            }
            mTts.shutdown();
        }
        super.onDestroy();
    }

    private void init() {
        mTts = new TextToSpeech(getBaseContext(), new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
                if(status == TextToSpeech.SUCCESS) {
                } else{
                    // todo: fail 시 처리
                    startActivity(getSettingActIntent());
                }
            }
        });
    }

    /** 언어 선택 */
    public void setLanguage(Locale locale){
        if(mTts!=null)
            mTts.setLanguage(locale);
    }

    public void setPitch(float value){
        if(mTts!=null)
            mTts.setPitch(value);
    }

    /** 속도 선택 */
    public void setSpeechRate(float value){
        if(mTts!=null)
            mTts.setSpeechRate(value);
    }

    /** TTS 설정 으로 이동 */
    public Intent getSettingActIntent(){
        Intent intent = new Intent();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH){
            intent.setAction("com.android.settings.TTS_SETTINGS");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        }else {
            intent.addCategory(Intent.CATEGORY_LAUNCHER);
            intent.setComponent(new ComponentName("com.android.settings", "com.android.settings.TextToSpeechSettings"));
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        }
        return intent;
    }

    /** 재생 */
    public void speak(String text, int resId){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
            if(mTts != null)
                mTts.speak(text, mQueue, null, ""+resId);
        }else {
            HashMap<String, String> map = new HashMap<>();
            map.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, ""+resId);
            if(mTts != null)
                mTts.speak(text, mQueue, map);
        }
    }
}


날씨 : 시원함, 뛰기 좋은 날씨, 미세먼지 조금

        2k 지나야 땀나오는 정도

체중 : 71.6kg

후기 : 물을 적게 마셔서 뛰었는데도, 갈증이 많이 나지는 않음

         but 몸이 무거웠음. 다리가 땡겨서 그랬나


    




'달리기 흔적' 카테고리의 다른 글

[5km] 2017년 4월 27일 목요일  (0) 2017.04.27
[5km] 2017년 4월 25일 화요일  (0) 2017.04.25
[5km] 2017년 4월 18일  (0) 2017.04.18
[10km] 2017년 4월 16일  (0) 2017.04.16
[5km] 2017년 4월 13일  (0) 2017.04.13

+ Recent posts