android2018. 7. 16. 16:00

<activity android:name=".IntentActivity">

<intent-filter>

<action android:name="android.intent.action.VIEW" />

<action android:name="com.test.simpletest.SEARCH" />

</intent-filter>

</activity>



cli에서 테스트

am start -a com.test.simpletest.SEARCH -n com.test.simpletest/com.test.simpletest.IntentActivity


Other activity.



private Intent getCustomIntent(){
	final String START_INTENT = "com.test.simpletest.SEARCH";
	final String ACTIVITY_NAME = "com.test.simpletest.IntentActivity";
	final String HOME_PACKAGE_NAME = "com.test.simpletest";
	Intent intent = new Intent(START_INTENT);
	ComponentName name = new ComponentName(HOME_PACKAGE_NAME, ACTIVITY_NAME);
	intent.setComponent(name);
	//Same application에서는 아래의 Flag를 사용하지 않아야 호출 됩니다.
	/*intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
			| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);*/
	return intent;
}

'android' 카테고리의 다른 글

MediaPlayer  (0) 2018.07.18
Single Fragment 예제  (0) 2018.07.16
tutorialspoint  (0) 2018.07.16
custom view tutorial 따라하기 3  (0) 2018.07.16
custom view tutorial 따라하기 2  (0) 2018.07.13
Posted by easy16
android2018. 7. 16. 11:51

안드로이드 예제가 필요할 때 참조

https://www.tutorialspoint.com/android/android_text_to_speech.htm

'android' 카테고리의 다른 글

Single Fragment 예제  (0) 2018.07.16
Custom Intent로 app 실행하기  (0) 2018.07.16
custom view tutorial 따라하기 3  (0) 2018.07.16
custom view tutorial 따라하기 2  (0) 2018.07.13
custom view tutorial 따라하기 1  (0) 2018.07.12
Posted by easy16
android2018. 7. 16. 11:14




Createing vies from scrach의 경우, Orientation 변경 시 view의 state 값이 저장되지 않는다.

Combining existing view의 경우는 view의 ID가 있으면 state 저장하도록 구현되어있음.


Tip)

An EditText by default will save its state, as long as an ID is provided in the layout.

That last part is important: without an ID no view will be able to save and restore state.



View clas의 BaseSavedState 를 확장하여 저장하고 싶은 값을 추가해보자.

알아야할 두가지 포인트는 constructor에서 restoring 시점에 Parcelable 객체를 받아온다는 것.

그리고 writeToParcel 부분에서 원하는 데이터를 저장한다는 것이다.

결론적으로 writeToParcel를 override하고, 2nd Constructor에서 값을 read하면 된다.




SavedState.java

import android.os.Parcel;
import android.os.Parcelable;
import android.view.View;

public class SavedState extends View.BaseSavedState {
    int value;

    public SavedState(Parcelable superState) {
        super(superState);
    }
    private SavedState(Parcel in ){
        super(in);
        value = in.readInt();
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        super.writeToParcel(out, flags);
        out.writeInt(value);
    }

    public static final Parcelable.Creator CREATOR=
        new Parcelable.Creator(){
            public SavedState createFromParcel (Parcel in ){
                return new SavedState(in);

            }

            @Override
            public SavedState[] newArray(int i) {
                return new SavedState[0];
            }
        };
}


ValueBar.java

    @Override
    protected Parcelable onSaveInstanceState() {
        Parcelable superState = super.onSaveInstanceState();
        SavedState ss = new SavedState(superState);
        ss.value = currentValue;
        Log.d("hello","onSaveInstanceState -> currentValue ="+currentValue);
        return ss;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        SavedState ss = (SavedState) state;
        super.onRestoreInstanceState(ss.getSuperState());
        currentValue=ss.value;
        Log.d("hello","onRestoreInstanceState -> currentValue ="+currentValue);
    }


//값을 위 두개의 callback의 사용 여부를 아래의 함수로 명시적으로 표시 가능하다.

//false 선택시, 호출되지 않으며 default는 true로 설정되어있다.

setSaveEnabled(true);





테스트를 위해 orientation을 변경하는 방법은 android:configChanges를 아래와 같이 설정 후, 

아래의 코드를 사용했다.


Manifest의 activity에 아래와 같이 


<activity android:name=".MainActivity"

android:configChanges="orientation|keyboardHidden"

>



if ( getRequestedOrientation() ==ActivityInfo.SCREEN_ORIENTATION_PORTRAIT )
	setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
else
	setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);


출처 : 

https://www.intertech.com/Blog/android-custom-view-tutorial-part-3-saving-state/

https://developer.android.com/reference/android/app/Activity

https://stackoverflow.com/questions/15632360/android-manual-screen-orientation-without-restarting-the-activity

'android' 카테고리의 다른 글

Custom Intent로 app 실행하기  (0) 2018.07.16
tutorialspoint  (0) 2018.07.16
custom view tutorial 따라하기 2  (0) 2018.07.13
custom view tutorial 따라하기 1  (0) 2018.07.12
Simple voice search test2  (0) 2018.07.11
Posted by easy16
android2018. 7. 13. 18:00


fully custom view를 생성하기 위해 아래의 것들을 수행한다.

custom attributes를 정의하고 사용.
-create attrs.xml, dimes-valuebars.xml
-load them from source code while initializing.
Measuring the View
-override onMeasure method
Drawing to the Canvas
Drawing shapes
-override onDraw method
Drawing text

invalidate() View에 변경 사항이 있을 때, 다시 그리도록 호출
requestLayout() View에 remeasure 가 필요한 상황에서 호출되며 전체 레이아웃에 영향을 준다.

The custom attributes will need to be read in and assigned in the init method. 
AttributeSet은 obtainStyledAttributes() 함수를 통해 가져다 access한다.
TypedArray를 통해 resource에 정의되어 역참조된 스타일과 값들을 쉽게 사용가능. (color나 size 등 xml에 정의된 녀석들을 코드상에서 쉽게 사용 가능)
Initialize는 되도록 onDraw 호출되기전에 하는 것이 좋다. 당연히 onDraw할 때 연산이 있으면 성능상 좋을리 없음.
Canvas, Paint는 우선 그림을 그리기 위한 툴킷과 자료형으로 이해하고 넘어가자.

사용자 정의된 attribute를 정의하고 로드 하는 방법을 잘 보도록 하자.

-measure 및 drawing은 직접 그려보지 않고는 이해하기 쉽지 않아 보이므로 필요한 경우 연습을 해보도록 하자.

res/values/attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ValueBar">
        <attr name="barHeight" format="dimension"/>
        <attr name="circleRadius" format="dimension"/>
        <attr name="spaceAfterBar" format="dimension"/>
        <attr name="circleTextSize" format="dimension"/>
        <attr name="maxValueTextSize" format="dimension"/>
        <attr name="labelTextSize" format="dimension"/>
        <attr name="labelTextColor" format="color" />
        <attr name="maxValueTextColor" format="color"/>
        <attr name="circleTextColor" format="color"/>
        <attr name="baseColor" format="color"/>
        <attr name="fillColor" format="color"/>
        <attr name="labelText" format="string"/>
    </declare-styleable>
</resources>

res/values/dimens-valueBar.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="value_bar_height">60dp</dimen>
    <dimen name="value_bar_padding_top">16dp</dimen>
    <dimen name="value_bar_barHeight">10dp</dimen>
    <dimen name="value_bar_circleRadius">12dp</dimen>
    <dimen name="value_bar_circleTextSize">14dp</dimen>
    <dimen name="value_bar_labelTextSize">18dp</dimen>
    <dimen name="value_bar_maxValueTextSize">24dp</dimen>
    <dimen name="value_bar_padding_horizontal">12dp</dimen>
    <dimen name="value_bar_spaceAfterBar">14dp</dimen>
</resources>

 

import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.View; import com.test.simpletest.R; public class ValueBar extends View { private int barHeight; private int circleRadius; private int spaceAfterBar; private int circleTextSize; private int maxValueTextSize; private int labelTextSize; private int labelTextColor; private int currentValueTextColor; private int circleTextColor; private int baseColor; private int fillColor; private String labelText; private int maxValue=100;//default private int currentValue=50; private Paint labelPaint; private Paint maxValuePaint; private Paint barBasePaint; private Paint circlePaint; private Paint barFillPaint; private Paint currentValuePaint; private float valueToDraw; public void setMaxValue(int maxValue){ this.maxValue = maxValue; invalidate(); requestLayout(); } public void setValue( int newValue ){ if (newValue < 0){ currentValue=0; } else if ( newValue > maxValue ){ currentValue=maxValue; } else { currentValue= newValue; } invalidate(); } public ValueBar(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(context, attrs); } private void init(Context context, AttributeSet attrs) { TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ValueBar,0 ,0); barHeight = ta.getDimensionPixelSize(R.styleable.ValueBar_barHeight,0); circleRadius = ta.getDimensionPixelSize(R.styleable.ValueBar_circleRadius,0); spaceAfterBar = ta.getDimensionPixelSize(R.styleable.ValueBar_spaceAfterBar,0); circleTextSize = ta.getDimensionPixelSize(R.styleable.ValueBar_circleTextSize, 0); maxValueTextSize = ta.getDimensionPixelSize(R.styleable.ValueBar_maxValueTextSize, 0); labelTextSize = ta.getDimensionPixelSize(R.styleable.ValueBar_labelTextSize, 0); labelTextColor = ta.getColor(R.styleable.ValueBar_labelTextColor, Color.BLACK); currentValueTextColor = ta.getColor(R.styleable.ValueBar_maxValueTextColor, Color.BLACK); circleTextColor = ta.getColor(R.styleable.ValueBar_circleTextColor, Color.BLACK); baseColor = ta.getColor(R.styleable.ValueBar_baseColor, Color.BLACK); fillColor = ta.getColor(R.styleable.ValueBar_fillColor, Color.BLACK); labelText = ta.getString(R.styleable.ValueBar_labelText); ta.recycle(); labelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); labelPaint.setTextSize(labelTextSize); labelPaint.setColor(labelTextColor); labelPaint.setTextAlign(Paint.Align.LEFT); labelPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); maxValuePaint = new Paint(Paint.ANTI_ALIAS_FLAG); maxValuePaint.setTextSize(maxValueTextSize); maxValuePaint.setColor(currentValueTextColor); maxValuePaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); maxValuePaint.setTextAlign(Paint.Align.RIGHT); barBasePaint = new Paint(Paint.ANTI_ALIAS_FLAG); barBasePaint.setColor(baseColor); barFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG); barFillPaint.setColor(fillColor); circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); circlePaint.setColor(fillColor); currentValuePaint = new Paint(Paint.ANTI_ALIAS_FLAG); currentValuePaint.setTextSize(circleTextSize); currentValuePaint.setColor(circleTextColor); currentValuePaint.setTextAlign(Paint.Align.CENTER); } @Override protected void onDraw(Canvas canvas) { drawLabel(canvas); drawBar(canvas); drawMaxValue(canvas); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec)); } private int measureHeight(int measureSpec){ int size = getPaddingTop() + getPaddingBottom(); size += labelPaint.getFontSpacing(); float maxValueTextSpacing = maxValuePaint.getFontSpacing(); size += Math.max(maxValueTextSpacing, Math.max(barHeight, circleRadius * 2)); return resolveSizeAndState(size, measureSpec,0); } private int measureWidth(int measureSpec){ int size = getPaddingLeft() + getPaddingRight(); Rect bounds = new Rect(); labelPaint.getTextBounds(labelText, 0, labelText.length(), bounds); size += bounds.width(); return resolveSizeAndState(size, measureSpec,0); } private void drawLabel(Canvas canvas){ float x = getPaddingLeft(); Rect bounds= new Rect(); labelPaint.getTextBounds(labelText, 0, labelText.length(), bounds); float y = getPaddingTop() + bounds.height(); canvas.drawText(labelText, x, y, labelPaint); } private void drawBar(Canvas canvas){ String maxValueString = String.valueOf(maxValue); Rect maxValueRect =new Rect(); maxValuePaint.getTextBounds(maxValueString, 0 , maxValueString.length(), maxValueRect); float barLength = getWidth() - getPaddingRight() - getPaddingLeft() - circleRadius - maxValueRect.width() - spaceAfterBar; float barCenter = getBarCenter(); float halfBarheight = barHeight/2; float top = barCenter - halfBarheight; float bottom =barCenter + halfBarheight; float left = getPaddingLeft(); float right = getPaddingLeft() + barLength; RectF rect = new RectF(left,top,right,bottom); canvas.drawRoundRect(rect, halfBarheight, halfBarheight, barBasePaint); float percentFilled = (float) currentValue / (float) maxValue; float fillLength = barLength * percentFilled; float fillPosition = left + fillLength; RectF fillRect = new RectF(left,top, fillPosition, bottom); canvas.drawRoundRect(fillRect, halfBarheight,halfBarheight,barFillPaint); canvas.drawCircle(fillPosition, barCenter, circleRadius, circlePaint); Rect bounds = new Rect(); String valueString = String.valueOf(Math.round(currentValue)); currentValuePaint.getTextBounds(valueString, 0, valueString.length(), bounds); float y = barCenter + (bounds.height() / 2); canvas.drawText(valueString, fillPosition, y, currentValuePaint); } private float getBarCenter(){ float barCenter = (getHeight() - getPaddingTop() - getPaddingBottom())/ 2; barCenter += getPaddingTop() + .1f * getHeight();//move it down a bit return barCenter; } private void drawMaxValue(Canvas canvas){ String maxValue = String.valueOf(this.maxValue); Rect maxValueRect = new Rect(); maxValuePaint.getTextBounds(maxValue,0 ,maxValue.length(), maxValueRect); float xPos = getWidth() - getPaddingRight(); float yPos = getBarCenter() + maxValueRect.height()/2; canvas.drawText(maxValue, xPos, yPos, maxValuePaint); } }




출처 : https://www.intertech.com/Blog/android-custom-view-tutorial-part-2-custom-attributes-drawing-and-measuring/


'android' 카테고리의 다른 글

tutorialspoint  (0) 2018.07.16
custom view tutorial 따라하기 3  (0) 2018.07.16
custom view tutorial 따라하기 1  (0) 2018.07.12
Simple voice search test2  (0) 2018.07.11
Simple voice search test  (0) 2018.07.11
Posted by easy16
android2018. 7. 12. 17:10

custom view tutorial 따라하기 1
 
 
There are generally two approaches to creating your own view

1, extend an existing view.
we will be extending an existing layout and combining existing views to form a new Android custom view.
2, create one from scratch (well, not totally from scratch since you will still be extending the View class)


테스트에 사용한 res는 아래의 경로에서 확인


RelativeLayout확장하고, init 부분에 inflate하여 가져온 rootView 뷰를 통해
하위 view에 접근한다는 것만 집고 넘어가자.

 
public class ValueSelector extends RelativeLayout{

    private int minValue = Integer.MIN_VALUE;
    private int maxValue = Integer.MAX_VALUE;

    private int REPEAT_INTERNAL_MS = 100;
    Handler mHandler=new Handler();
    public int getMinValue(){
        return minValue;

    }
    public void setMinValue(int minValue){
        this.minValue=minValue;
    }
    public int getMaxValue(){
        return maxValue;
    }
    public void setMaxValue(int maxValue){
        this.maxValue=maxValue;
    }



    public int getValue(){
        return Integer.valueOf(valueTextView.getText().toString());
    }
    public void setValue(int newValue){
        int value = newValue;
        if( value < minValue)
            value=minValue;
        else if (value > maxValue)
            value=maxValue;
        valueTextView.setText(String.valueOf(value));
    }

    View rootView;
    TextView valueTextView;
    View minusButton;
    View plusButton;

    public ValueSelector (Context context){
        super(context);
        init(context);

    }

    public ValueSelector(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    /**
     * init method will inflate the layout, get references to all of the child views, and setup the buttons
     * @param context
     */
    private void init (Context context){
        rootView = inflate(context, R.layout.value_selector, this);
        valueTextView = (TextView) rootView.findViewById(R.id.valueTextView);

        minusButton = rootView.findViewById(R.id.minusButton);
        plusButton = rootView.findViewById(R.id.plusButton);


        minusButton.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                decrementValue();
            }
        });
        plusButton.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                incrementValue();
            }
        });
        plusButton.setOnLongClickListener(new View.OnLongClickListener(){
            @Override
            public boolean onLongClick(View view) {
                mHandler.post(new AutoIncrementer());
                return false;
            }
        });
        minusButton.setOnLongClickListener(new View.OnLongClickListener(){

            @Override
            public boolean onLongClick(View view) {
                mHandler.post(new AutoDecrementer());
                return false;
            }
        });
    }

    private void decrementValue() {
        int currentVal= Integer.valueOf(valueTextView.getText().toString());
        if (currentVal > minValue )
            valueTextView.setText(String.valueOf(currentVal-1));
    }

    private void incrementValue() {

        int currentVal= Integer.valueOf(valueTextView.getText().toString());
        if( currentVal < maxValue ){
            valueTextView.setText(String.valueOf(currentVal+1));
        }
    }
    private class AutoIncrementer implements Runnable{
        @Override
        public void run() {
            if ( plusButton.isPressed() ){
                incrementValue();
                getHandler().postDelayed( new AutoIncrementer(), REPEAT_INTERNAL_MS);
            }
        }
    }
    private class AutoDecrementer implements Runnable{
        @Override
        public void run() {
            if( minusButton.isPressed() ){
                decrementValue();
                getHandler().postDelayed(new AutoDecrementer(),REPEAT_INTERNAL_MS);
            }
        }
    }
}




res/layout/value_selector.xml

You also might notice that the root node in the xml is merge. 
What does that do?  Since ValueSelector extends RelativeLayout, 
if we inflated a RelativeLayout, we would end up with a view that contains a RelativeLayout as its only child.  
By using merge, we can avoid that unnecessary RelativeLayout

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/valueSelector_margin_top"
        android:textSize="@dimen/valueSelector_text"
        android:text="0"
        android:enabled="false"
        android:background="@null"
        android:textColor="#000000"
        android:layout_centerHorizontal="true"
        android:id="@+id/valueTextView" />
    <TextView
        android:id="@+id/valueLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="@dimen/valueSelector_label_text"
        android:text="@string/valueSelector_label"
        android:layout_below="@+id/valueTextView"
        android:layout_centerHorizontal="true"/>
    <ImageView
        android:src="@drawable/valueselect_minus_state"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/valueSelector_button_hMargin"
        android:layout_marginBottom="@dimen/valueSelector_button_hMargin"
        android:layout_marginRight="@dimen/valueSelector_button_insideMargin"
        android:id="@+id/minusButton"
        android:clickable="true"
        android:focusable="true"
        android:layout_centerVertical="true"
        android:layout_alignRight="@+id/valueLabel"
        />

    <ImageView
        android:src="@drawable/valueselect_plus_state"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/valueSelector_button_hMargin"
        android:layout_marginBottom="@dimen/valueSelector_button_hMargin"
        android:layout_marginLeft="@dimen/valueSelector_button_insideMargin"
        android:id="@+id/plusButton"
        android:clickable="true"
        android:focusable="true"
        android:layout_centerVertical="true"
        android:layout_alignLeft="@+id/valueLabel" />
</merge>


res/drawable/valueselect_minus_state.xml
drawable에 xml을 정의하여 button이 눌렸을 때와 아닌 경우의 image를 교차로 보여줌.

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/valueselect_pressed" />
    <item android:drawable="@drawable/valueselect_minus" />
</selector>


이제 다 만들었으니 layout에 가져다 쓰면 잘 돈다.

res/layout/activity_main.xml

<com.test.simpletest.customview.ValueSelector
android:id="@+id/valueSelector"
android:layout_width="match_parent"
android:layout_height="@dimen/valueSelector_height"
android:layout_marginLeft="@dimen/valueSelector_hMargin"
android:layout_marginRight="@dimen/valueSelector_hMargin">
</com.test.simpletest.customview.ValueSelector>






'android' 카테고리의 다른 글

custom view tutorial 따라하기 3  (0) 2018.07.16
custom view tutorial 따라하기 2  (0) 2018.07.13
Simple voice search test2  (0) 2018.07.11
Simple voice search test  (0) 2018.07.11
NDK API는 binder를 지원하지 않는다.  (0) 2018.07.03
Posted by easy16
android2018. 7. 11. 16:13
간단히 voice input을 Toast로 출력하는 예제

/* Call Activity for Voice Input */
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);

intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "en-US");

try {
    startActivityForResult(intent, 1);
} catch (ActivityNotFoundException a) {
    Toast.makeText(context, "Oops! Your device doesn't support Speech to Text",Toast.LENGTH_SHORT).show();
}


/* When Mic activity close */

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    switch (requestCode) {
    case 1: {
        if (resultCode == Activity.RESULT_OK && null != data) {
            String yourResult = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS).get(0);
        }
        break;
    }
    }
}

출처 : https://stackoverflow.com/questions/18049157/how-to-programmatically-initiate-a-google-now-voice-search?lq=1

'android' 카테고리의 다른 글

custom view tutorial 따라하기 2  (0) 2018.07.13
custom view tutorial 따라하기 1  (0) 2018.07.12
Simple voice search test  (0) 2018.07.11
NDK API는 binder를 지원하지 않는다.  (0) 2018.07.03
hidl simple example  (4) 2018.06.25
Posted by easy16
android2018. 7. 11. 15:26
심플 테스트 

layout

<LinearLayout 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:orientation="vertical" >  
  
    <TextView  
        android:id="@+id/textView1"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:paddingBottom="4dip"  
        android:text="Click the button " />  
  
    <EditText  
        android:id="@+id/editText1"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:ems="10" >  
  
        <requestFocus />  
    </EditText>  
  
    <Button android:id="@+id/speakButton"  
        android:layout_width="fill_parent"  
        android:onClick="speakButtonClicked"  
        android:layout_height="wrap_content"  
        android:text="Click here!" />  
  
</LinearLayout>


 code
import android.content.Intent;  
import android.content.pm.PackageManager;  
import android.content.pm.ResolveInfo;  
import android.speech.RecognizerIntent;  
import android.support.v7.app.AppCompatActivity;  
import android.os.Bundle;  
import android.text.Editable;  
import android.text.TextWatcher;  
import android.view.View;  
import android.widget.AdapterView;  
import android.widget.ArrayAdapter;  
import android.widget.Button;  
import android.widget.EditText;  
import android.widget.ListView;  
import android.widget.TextView;  
import android.widget.Toast;  
import java.util.ArrayList;  
import java.util.List;  
public class MainActivity extends AppCompatActivity  
{  
    EditText ed;  
    TextView tv;  
    private static final int REQUEST_CODE = 1234;  
    Button speak;@  
        Override  
protected void onCreate(Bundle savedInstanceState)  
{  
    super.onCreate(savedInstanceState);  
    setContentView(R.layout.activity_main);  
    final Button speak = (Button) findViewById(R.id.speakButton);  
    ed = (EditText) this.findViewById(R.id.editText1);  
    tv = (TextView) this.findViewById(R.id.textView1);  
    // Disable button if no recognition service is present  
    PackageManager pm = getPackageManager();  
    List < ResolveInfo > activities = pm.queryIntentActivities(new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);  
    if (activities.size() == 0)  
    {  
        speak.setEnabled(false);  
        speak.setText("Recognizer not present");  
    }  
    ed.addTextChangedListener(new TextWatcher()  
    {@  
            Override  
    public void beforeTextChanged(CharSequence s, int start, int count, int after)  
    {  
        // TODO Auto-generated method stub  
    }@  
            Override  
    public void onTextChanged(CharSequence s, int start, int before, int count)  
    {  
        // TODO Auto-generated method stub  
    }@  
            Override  
    public void afterTextChanged(Editable s)  
    {  
        // TODO Auto-generated method stub  
        speak.setEnabled(false);  
    }  
    });  
}  
    /** 
     * Handle the action of the button being clicked 
     */  
    public void speakButtonClicked(View v)  
    {  
        startVoiceRecognitionActivity();  
    }  
    /** 
     * Fire an intent to start the voice recognition activity. 
     */  
    private void startVoiceRecognitionActivity()  
    {  
        Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);  
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);  
        intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Voice searching...");  
        startActivityForResult(intent, REQUEST_CODE);  
    }  
    /** 
     * Handle the results from the voice recognition activity. 
     */  
    @  
            Override  
    protected void onActivityResult(int requestCode, int resultCode, Intent data)  
    {  
        if (requestCode == REQUEST_CODE && resultCode == RESULT_OK)  
        {  
            // Populate the wordsList with the String values the recognition engine thought it heard  
            final ArrayList < String > matches = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);  
            if (!matches.isEmpty())  
            {  
                String Query = matches.get(0);  
                ed.setText(Query);  
                speak.setEnabled(false);  
            }  
        }  
        super.onActivityResult(requestCode, resultCode, data);  
    }  
  
}  


출처 : https://www.c-sharpcorner.com/article/create-voice-search-android-application-using-android-studio/



'android' 카테고리의 다른 글

custom view tutorial 따라하기 1  (0) 2018.07.12
Simple voice search test2  (0) 2018.07.11
NDK API는 binder를 지원하지 않는다.  (0) 2018.07.03
hidl simple example  (4) 2018.06.25
android ir to android keycode mapping  (0) 2018.06.21
Posted by easy16
android2018. 7. 3. 18:40

NDK api는 binder를 지원하지 않음. 즉, NDK로 system service를 구성할 수 없음. 


따라서 native 환경에서 binder를 사용하여 service를 추가하기 위해서는

System permission을 얻은 상태에서 구현해야함 (platform 단위에서 빌드) 


아래의 stackoverflow 참조

: https://stackoverflow.com/questions/14215462/how-to-create-a-android-native-service-and-use-binder-to-communicate-with-it

'android' 카테고리의 다른 글

Simple voice search test2  (0) 2018.07.11
Simple voice search test  (0) 2018.07.11
hidl simple example  (4) 2018.06.25
android ir to android keycode mapping  (0) 2018.06.21
Android Custom KeyCode 추가  (0) 2018.06.21
Posted by easy16
android2018. 6. 25. 17:03

mysimptest.tgz

simple_hidl.tgz


http://devarea.com/android-hidl-and-project-treble/#.WzGVeaczaUk


위의 사이트의 tutorial을 직접 추가해봤음.

두 가지를 수정하니 내가 구성한 환경에서 돌아가는 것을 확인함.

- android.hardware.simple@2.0-impl.so을 sharelib으로 링크하는 경우, /vendor/lib/hw에 위치한 해당 so를 인식하지 못함.

- *-impl.so의 경우, framework에서 direct로 링크하여 쓰는 경우가 없음.

- 따라서 tutorial 내용과 다르게 getInstance 메소드 대신, HIDL_FETCH_ISimphw을 사용하여 위의 문제들을 모두 회피 가능.

- 굳이 HIDL_FETCH_ISimphw의 내용을 따라가보진 않았으나, 해당 함수 호출시, *-impl.so 를 링크하는 부분이 hidl의 어딘가에는 구현되어 있을거라 추측함.


1. add simple directory

mkdir -p hardware/interfaces/simple/2.0/default 



2. create hal file
package android.hardware.simple@2.0;

interface ISimphw {
    simpfn(int32_t valueIn) generates (int32_t valueRet);
};
3. use hidl-gen to make HAL files. make hidl.sh
PACKAGE=android.hardware.simple@2.0
LOC=hardware/interfaces/simple/2.0/default/
HIDL_GEN=out/host/linux-x86/bin/hidl-gen
# make hidl-gen -j64
$HIDL_GEN -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE
$HIDL_GEN -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE
#./hidl.sh

check auto gen files
 

hardware/interfaces/simple/2.0/
├── ISimphw.hal
└── default //auto gen
    ├── Android.bp
    ├── Simphw.cpp
    └── Simphw.h

leej5@LeeJ5:~/workspace/sapphire/hardware/interfaces/simple/2.0/default$ cat Android.bp
cc_library_shared {
    name: "android.hardware.simple@2.0-impl",
    relative_install_path: "hw",
    proprietary: true,
    srcs: [
        "Simphw.cpp",
    ],
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "libutils",
        "android.hardware.simple@2.0",
        "android.hidl.base@1.0",
    ],
}
leej5@LeeJ5:~/workspace/sapphire/hardware/interfaces/simple/2.0/default$ cat Simphw.cpp
#include "Simphw.h"

namespace android {
namespace hardware {
namespace simple {
namespace V2_0 {
namespace implementation {

// Methods from ::android::hardware::simple::V2_0::ISimphw follow.
Return Simphw::simpfn(int32_t valueIn) {
    // TODO implement
    return int32_t {};
}

// Methods from ::android::hidl::base::V1_0::IBase follow.

ISimphw* HIDL_FETCH_ISimphw(const char* /* name */) {
    return new Simphw();
}

}  // namespace implementation
}  // namespace V2_0
}  // namespace simple
}  // namespace hardware
}  // namespace android

leej5@LeeJ5:~/workspace/sapphire/hardware/interfaces/simple/2.0/default$ cat Simphw.h
#ifndef ANDROID_HARDWARE_SIMPLE_V2_0_SIMPHW_H
#define ANDROID_HARDWARE_SIMPLE_V2_0_SIMPHW_H

#include 
#include 
#include 

namespace android {
namespace hardware {
namespace simple {
namespace V2_0 {
namespace implementation {

using ::android::hardware::simple::V2_0::ISimphw;
using ::android::hidl::base::V1_0::DebugInfo;
using ::android::hidl::base::V1_0::IBase;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;

struct Simphw : public ISimphw {
    // Methods from ::android::hardware::simple::V2_0::ISimphw follow.
    Return simpfn(int32_t valueIn) override;

    // Methods from ::android::hidl::base::V1_0::IBase follow.

};

extern "C" ISimphw* HIDL_FETCH_ISimphw(const char* name);

}  // namespace implementation
}  // namespace V2_0
}  // namespace simple
}  // namespace hardware
}  // namespace android

#endif  // ANDROID_HARDWARE_SIMPLE_V2_0_SIMPHW_H
4. run below script to update android mk and bp export PATH=$PATH:/home/leej5/workspace/sapphire/out/host/linux-x86/bin/ ./hardware/interfaces/update-makefiles.sh
simple/
├── 2.0
│   ├── Android.bp
│   ├── Android.mk
│   ├── ISimphw.hal
│   └── default
│       ├── Android.bp
│       ├── Simphw.cpp
│       └── Simphw.h
└── Android.bp

leej5@LeeJ5:~/workspace/sapphire/hardware/interfaces$ cat simple/Android.bp
// This is an autogenerated file, do not edit.
subdirs = [
    "2.0",
    "2.0/default",
]
2.0/Android.bp
// This file is autogenerated by hidl-gen. Do not edit manually.

filegroup {
    name: "android.hardware.simple@2.0_hal",
    srcs: [
        "ISimphw.hal",
    ],
}

genrule {
    name: "android.hardware.simple@2.0_genc++",
    tools: ["hidl-gen"],
    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.simple@2.0",
    srcs: [
        ":android.hardware.simple@2.0_hal",
    ],
    out: [
        "android/hardware/simple/2.0/SimphwAll.cpp",
    ],
}

genrule {
    name: "android.hardware.simple@2.0_genc++_headers",
    tools: ["hidl-gen"],
    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.simple@2.0",
    srcs: [
        ":android.hardware.simple@2.0_hal",
    ],
    out: [
        "android/hardware/simple/2.0/ISimphw.h",
        "android/hardware/simple/2.0/IHwSimphw.h",
        "android/hardware/simple/2.0/BnHwSimphw.h",
        "android/hardware/simple/2.0/BpHwSimphw.h",
        "android/hardware/simple/2.0/BsSimphw.h",
    ],
}

cc_library_shared {
    name: "android.hardware.simple@2.0",
    defaults: ["hidl-module-defaults"],
    generated_sources: ["android.hardware.simple@2.0_genc++"],
    generated_headers: ["android.hardware.simple@2.0_genc++_headers"],
    export_generated_headers: ["android.hardware.simple@2.0_genc++_headers"],
    vendor_available: true,
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "libhwbinder",
        "liblog",
        "libutils",
        "libcutils",
        "android.hidl.base@1.0",
    ],
    export_shared_lib_headers: [
        "libhidlbase",
        "libhidltransport",
        "libhwbinder",
        "libutils",
        "android.hidl.base@1.0",
    ],
}
2.0/Android.mk
# This file is autogenerated by hidl-gen. Do not edit manually.

LOCAL_PATH := $(call my-dir)

################################################################################

include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.simple-V2.0-java
LOCAL_MODULE_CLASS := JAVA_LIBRARIES

intermediates := $(call local-generated-sources-dir, COMMON)

HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)

LOCAL_JAVA_LIBRARIES := \
    android.hidl.base-V1.0-java \


#
# Build ISimphw.hal
#
GEN := $(intermediates)/android/hardware/simple/V2_0/ISimphw.java
$(GEN): $(HIDL)
$(GEN): PRIVATE_HIDL := $(HIDL)
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/ISimphw.hal
$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
$(GEN): PRIVATE_CUSTOM_TOOL = \
        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
        -Ljava \
        -randroid.hardware:hardware/interfaces \
        -randroid.hidl:system/libhidl/transport \
        android.hardware.simple@2.0::ISimphw

$(GEN): $(LOCAL_PATH)/ISimphw.hal
    $(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(GEN)
include $(BUILD_JAVA_LIBRARY)


################################################################################

include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.simple-V2.0-java-static
LOCAL_MODULE_CLASS := JAVA_LIBRARIES

intermediates := $(call local-generated-sources-dir, COMMON)

HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)



LOCAL_STATIC_JAVA_LIBRARIES := \
    android.hidl.base-V1.0-java-static \


#
# Build ISimphw.hal
#
GEN := $(intermediates)/android/hardware/simple/V2_0/ISimphw.java
$(GEN): $(HIDL)
$(GEN): PRIVATE_HIDL := $(HIDL)
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/ISimphw.hal
$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
$(GEN): PRIVATE_CUSTOM_TOOL = \
        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
        -Ljava \
        -randroid.hardware:hardware/interfaces \
        -randroid.hidl:system/libhidl/transport \
        android.hardware.simple@2.0::ISimphw

$(GEN): $(LOCAL_PATH)/ISimphw.hal
    $(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(GEN)
include $(BUILD_STATIC_JAVA_LIBRARY)



include $(call all-makefiles-under,$(LOCAL_PATH))
5. add empty files to hardware/interfaces/simple/2.0/default: android.hardware.simple@2.0-service.rc service.cpp results
leej5@LeeJ5:~/workspace/sapphire/hardware/interfaces$ tree simple/
simple/
├── 2.0
│   ├── Android.bp
│   ├── Android.mk
│   ├── ISimphw.hal
│   └── default
│       ├── Android.bp
│       ├── Simphw.cpp
│       ├── Simphw.h
│       ├── android.hardware.simple@2.0-service.rc
│       └── service.cpp
└── Android.bp

2 directories, 9 files
6.Implementing the HAL shared object: we need to add a new static function to return the service object (usually as a singleton) Simphw.h
#ifndef ANDROID_HARDWARE_SIMPLE_V2_0_SIMPHW_H
#define ANDROID_HARDWARE_SIMPLE_V2_0_SIMPHW_H

#include 
#include 
#include 

namespace android {
namespace hardware {
namespace simple {
namespace V2_0 {
namespace implementation {

using ::android::hardware::simple::V2_0::ISimphw;
using ::android::hidl::base::V1_0::DebugInfo;
using ::android::hidl::base::V1_0::IBase;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;

struct Simphw : public ISimphw {
    // Methods from ::android::hardware::simple::V2_0::ISimphw follow.
    Return simpfn(int32_t valueIn) override;
};

extern "C" ISimphw* HIDL_FETCH_ISimphw(const char* name);

}  // namespace implementation
}  // namespace V2_0
}  // namespace simple
}  // namespace hardware
}  // namespace android

#endif  // ANDROID_HARDWARE_SIMPLE_V2_0_SIMPHW_H
simple/2.0/default/Simphw.cpp 수정
#include "Simphw.h"

namespace android {
namespace hardware {
namespace simple {
namespace V2_0 {
namespace implementation {

// Methods from ::android::hardware::simple::V2_0::ISimphw follow.
Return Simphw::simpfn(int32_t valueIn) {
    // TODO implement
    return valueIn+100;
}

// Methods from ::android::hidl::base::V1_0::IBase follow.
ISimphw* HIDL_FETCH_ISimphw(const char* /* name */) {
    return new Simphw();
}

}  // namespace implementation
}  // namespace V2_0
}  // namespace simple
}  // namespace hardware
}  // namespace android

Note that if you want to support pass-through mode, you need to uncomment the HIDL_FETCH_ISimphw function In this example, we implemented the function as simple as possible (usually we will load the hardware module here) The generated Android.bp file build a shared library with the implementation – android.hardware.simple@2.0-impl Creating the Service To host the library we need to create a simple executable: service.cpp
#define LOG_TAG "android.hardware.simple@2.0-service"
 
#include 
 
#include 
 
#include "Simphw.h"
 
using android::hardware::simple::V2_0::ISimphw;
using android::hardware::simple::V2_0::implementation::Simphw;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::sp;
using android::hardware::defaultPassthroughServiceImplementation;

int main() {
    return defaultPassthroughServiceImplementation();
}
We create an instance of our implementation, Create a thread pool for the binder and register the current process as a service Note that the function regsiterAsService() is auto-generated by hidl-gen tool To make this service run automatically add init file: android.hardware.simple@2.0-service.rc
service simphwserv /vendor/bin/hw/android.hardware.simple@2.0-service
    class hal
    user root
    group root
    seclabel u:r:su:s0
For testing purpose I set the security label to su , we need to set SE Linux rules (I wrote it in the init.te file): ./yours/sepolicy/block/init.te
allow init vendor_file:file { execute };
allow init su:process { transition };
To tell the build system to build the service add the following to Android.bp (in directory default)
cc_binary {
    name: "android.hardware.simple@2.0-service",
    defaults: ["hidl_defaults"],
    proprietary: true,
    relative_install_path: "hw",
    srcs: ["service.cpp"],
    init_rc: ["android.hardware.simple@2.0-service.rc"],
 
    shared_libs: [
        "android.hardware.simple@2.0",
        "libhidlbase",
        "libhidltransport",
        "liblog",
        "libutils",
    ],
}
Add the following components to build/make/target/product/emulator.mk vi build/make/target/product/emulator.mk
PRODUCT_PACKAGES += \
    android.hardware.simple@2.0-impl \
    android.hardware.simple@2.0-service \
leej5@LeeJ5:~/android/hardware/interfaces/simple$ mm -j16 results
leej5@LeeJ5:~/workspace/sapphire/out/target/product/sapphire_tch/system$ find . -name "*simple*"
./lib/android.hardware.simple@2.0.so

leej5@LeeJ5:~/workspace/sapphire/out/target/product/sapphire_tch/vendor$ find . -name "*simple*"
./lib/hw/android.hardware.simple@2.0-impl.so
./etc/init/android.hardware.simple@2.0-service.rc
./bin/hw/android.hardware.simple@2.0-service
sapphire_tch:/ # lshal
All available passthrough implementations (all -impl.so files)
Interface                                                                               Server  Clients
android.hardware.audio.effect@2.0::I*/*                                                 N/A  
android.hardware.audio@2.0::I*/*                                                        N/A  
android.hardware.bluetooth@1.0::I*/*                                                    N/A  
android.hardware.boot@1.0::I*/*                                                         N/A  
android.hardware.drm@1.0::I*/*                                                          N/A  
android.hardware.graphics.allocator@2.0::I*/*                                           N/A  
android.hardware.graphics.composer@2.1::I*/*                                            N/A  
android.hardware.graphics.mapper@2.0::I*/*                                              N/A  
android.hardware.keymaster@3.0::I*/*                                                    N/A  
android.hardware.light@2.0::I*/*                                                        N/A  
android.hardware.memtrack@1.0::I*/*                                                     N/A  
android.hardware.power@1.0::I*/*                                                        N/A  
android.hardware.renderscript@1.0::I*/*                                                 N/A  
android.hardware.simple@2.0::I*/*                                                       N/A  
android.hardware.soundtrigger@2.0::I*/*                                                 N/A  
android.hardware.thermal@1.0::I*/*                                                      N/A  
android.hardware.tv.cec@1.0::I*/*                                                       N/A  
android.hardware.tv.input@1.0::I*/*                                                     N/A  
android.hidl.memory@1.0::I*/*                                                           N/A  
sapphire_tch:/ # ps -A | grep simp root 7315 1 7180 3376 binder_thread_read a7bed514 S android.hardware.simple@2.0-service sapphire_tch:/ # lshal
All binderized services (registered services through hwservicemanager)
Interface                                                                               Server  Clients
android.frameworks.displayservice@1.0::IDisplayService/default                          3573    3394
android.frameworks.schedulerservice@1.0::ISchedulingPolicyService/default               3780    3394
android.frameworks.sensorservice@1.0::ISensorManager/default                            3780    3394
android.hardware.audio.effect@2.0::IEffectsFactory/default                              3554    3658 3394
android.hardware.audio@2.0::IDevicesFactory/default                                     3554    3658 3394
android.hardware.bluetooth@1.0::IBluetoothHci/default                                   3555    3888 3394
android.hardware.boot@1.0::IBootControl/default                                         3396    3762 3394
android.hardware.configstore@1.0::ISurfaceFlingerConfigs/default                        3556    3394
android.hardware.drm@1.0::ICryptoFactory/default                                        3557    3394
android.hardware.drm@1.0::ICryptoFactory/widevine                                       3558    3394
android.hardware.drm@1.0::IDrmFactory/default                                           3557    3663 3394
android.hardware.drm@1.0::IDrmFactory/widevine                                          3558    3663 3394
android.hardware.graphics.allocator@2.0::IAllocator/default                             3559    3573 3394
android.hardware.graphics.composer@2.1::IComposer/default                               3560    3573 3394
android.hardware.keymaster@3.0::IKeymasterDevice/default                                3397    3662 3394
android.hardware.light@2.0::ILight/default                                              3561    3780 3394
android.hardware.media.omx@1.0::IOmx/default                                            3669    3666 3394
android.hardware.media.omx@1.0::IOmxStore/default                                       3669    3394
android.hardware.memtrack@1.0::IMemtrack/default                                        3562    3780 3394
android.hardware.power@1.0::IPower/default                                              3563    3780 3394
android.hardware.simple@2.0::ISimphw/default                                            7315    3394

as a simple test, make a binary project to vendor path. vendor/[yours]/simpleTest "servtest.cpp"

#define LOG_TAG "android.hardware.simple@2.0-service"
 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
 
#include
 
 
using android::hardware::simple::V2_0::ISimphw;
using android::sp;
 
 
int main() {
      int res;
      android::sp ser = ISimphw::getService();
 
      res = ser->simpfn(200);
 
      printf("val=%d\n",res);
 
      return 0; 
}
Android.bp
cc_binary {
    name: "mysimptest",
    defaults: ["hidl_defaults"],
    proprietary: true,
    srcs: ["servtest.cpp"],
 
    shared_libs: [
        "android.hardware.simple@2.0",
        "libhidlbase",
        "libhidltransport",
        "liblog",
        "libutils",
    ],
}
Add hal entry to the Manifest.xml file in my case~ add it here "/device/~~/treble.xml"
    
        android.hardware.simple
	hwbinder
        2.0
        
            ISimphw
            default
        
    


# mysimptest

val=300



'android' 카테고리의 다른 글

Simple voice search test  (0) 2018.07.11
NDK API는 binder를 지원하지 않는다.  (0) 2018.07.03
android ir to android keycode mapping  (0) 2018.06.21
Android Custom KeyCode 추가  (0) 2018.06.21
[NDK] so 포함한 apk가 so loading 실패 (3)  (0) 2018.06.19
Posted by easy16
android2018. 6. 21. 14:13
Ir key 값을 linux keycode로 매핑

ir.ikm

0xd52a0e86  TV2


bcm의 경우, linux_keys 변수에 등록된 key를 사용하여 ikm파일로부터 linux keycode로 매핑시켜줌

"nxif/libnexusir/nexusirmap.cpp" 


DEFINE_KEY(TV2),

Definition of Linux Keycode
"include/uapi/linux/input.h"

#define KEY_TV2        	    0x17a   //378

최종적으로는 bluetooth keylayout과 마찬가지로 아래 kl을 이용하여 android keycode로 변환 됨. 

 system/usr/keylayout/NexusIrHandler.kl


key 378   TV2





Posted by easy16