web.html


<script>
        function callbackFunctionName() {
            $('input[name=keyword]').focus();
        }
       
        $(function() {
            location.href = 'iwtapplink-command://initFocusWithSoftKeyboard?callback=callbackFunctionName';

        });
    </script>



android app

    public boolean shouldOverrideUrlLoading(WebView paramWebView, String paramString) {
        if (paramString.startsWith(activity.getString(R.string.appLinkIwtCommandInitFocusWithSoftKeyboard))) {
                InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);

                String callback = "callbackFunctionName";
                if(paramString.indexOf("?") > 0) {
                    try {
                        Map<String, String> queryStringMap = StringUtil.queryStringToMap(paramString.replace(activity.getString(R.string.appLinkIwtCommandInitFocusWithSoftKeyboard) + "?", ""));

                        if (!TextUtils.isEmpty(queryStringMap.get("callback"))) {
                            callback = queryStringMap.get("callback");
                        }
                    } catch (UnsupportedEncodingException uee) {

                    }
                }

                webView.loadUrl("javascript:" + callback + "();");

                return true;
            }

            return false;
        }

Posted by incree

2018/06/06 03:50 2018/06/06 03:50
, ,
Response
0 Trackbacks , 0 Comments
RSS :
http://www.incree.com/tc/incree/rss/response/395

Trackback URL : 이 글에는 트랙백을 보낼 수 없습니다

[Android]TextView Outline text

public class IATOutLineTextView extends AppCompatTextView {
public IATOutLineTextView(Context context) {
this(context, null);
}

public IATOutLineTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public IATOutLineTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);

int textColor = this.getCurrentTextColor();

TextPaint paint = this.getPaint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.MITER);
paint.setStrokeMiter(10);
this.setTextColor(Color.parseColor("#ff0000"));
paint.setStrokeWidth(10);
super.onDraw(canvas);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(0);
this.setTextColor(textColor);
super.onDraw(canvas);
}
}

Posted by incree

2018/04/21 07:16 2018/04/21 07:16
, ,
Response
0 Trackbacks , 0 Comments
RSS :
http://www.incree.com/tc/incree/rss/response/392

Trackback URL : 이 글에는 트랙백을 보낼 수 없습니다



MPAndroidChart custom BarchartRenderer Example

차트에 배경 이미지 넣기
막대에 그라데이션 적용

package com.incree.mpandroidchart.custom.barchartrenderer.example;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.WindowManager;
import android.widget.SeekBar;
import android.widget.TextView;

import com.github.mikephil.charting.animation.ChartAnimator;
import com.github.mikephil.charting.buffer.BarBuffer;
import com.github.mikephil.charting.charts.BarChart;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider;
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
import com.github.mikephil.charting.renderer.BarChartRenderer;
import com.github.mikephil.charting.utils.ColorTemplate;
import com.github.mikephil.charting.utils.Transformer;
import com.github.mikephil.charting.utils.Utils;
import com.github.mikephil.charting.utils.ViewPortHandler;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
protected BarChart mChart;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);

mChart = (BarChart) findViewById(R.id.chart1);

mChart.setDrawBarShadow(false);
mChart.setDrawValueAboveBar(true);

mChart.getDescription().setEnabled(false);

setData();

mChart.setRenderer(new MyBarChartRenderer(mChart, mChart.getAnimator(), mChart.getViewPortHandler()));
}

private void setData() {

float start = 1f;

ArrayList<BarEntry> yVals1 = new ArrayList<BarEntry>();

for (int i = 0; i < 12; i++) {
float mult = (500 + 1);
float val = (float) (Math.random() * mult);

yVals1.add(new BarEntry(i, val));
}

BarDataSet set1;

if (mChart.getData() != null &&
mChart.getData().getDataSetCount() > 0) {
set1 = (BarDataSet) mChart.getData().getDataSetByIndex(0);
set1.setValues(yVals1);
mChart.getData().notifyDataChanged();
mChart.notifyDataSetChanged();
} else {
set1 = new BarDataSet(yVals1, "The year 2017");

set1.setDrawIcons(false);

set1.setColors(ColorTemplate.MATERIAL_COLORS);

ArrayList<IBarDataSet> dataSets = new ArrayList<IBarDataSet>();
dataSets.add(set1);

BarData data = new BarData(dataSets);
data.setValueTextSize(10f);
data.setBarWidth(0.9f);

mChart.setData(data);
}
}

class MyBarChartRenderer extends BarChartRenderer {
public MyBarChartRenderer(BarDataProvider chart, ChartAnimator animator,
ViewPortHandler viewPortHandler) {
super(chart, animator, viewPortHandler);

initBuffers();
}

@Override
public void drawData(Canvas c) {
Drawable d = getResources().getDrawable(R.drawable.zzang);
d.setBounds(0, 0, c.getWidth(), c.getHeight());
d.draw(c);

super.drawData(c);
}

private RectF mBarShadowRectBuffer = new RectF();

@Override
protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) {
Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());

mBarBorderPaint.setColor(dataSet.getBarBorderColor());
mBarBorderPaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getBarBorderWidth()));

final boolean drawBorder = dataSet.getBarBorderWidth() > 0.f;

float phaseX = mAnimator.getPhaseX();
float phaseY = mAnimator.getPhaseY();

// draw the bar shadow before the values
if (mChart.isDrawBarShadowEnabled()) {
mShadowPaint.setColor(dataSet.getBarShadowColor());

BarData barData = mChart.getBarData();

final float barWidth = barData.getBarWidth();
final float barWidthHalf = barWidth / 2.0f;
float x;

for (int i = 0, count = Math.min((int)(Math.ceil((float)(dataSet.getEntryCount()) * phaseX)), dataSet.getEntryCount());
i < count;
i++) {

BarEntry e = dataSet.getEntryForIndex(i);

x = e.getX();

mBarShadowRectBuffer.left = x - barWidthHalf;
mBarShadowRectBuffer.right = x + barWidthHalf;

trans.rectValueToPixel(mBarShadowRectBuffer);

if (!mViewPortHandler.isInBoundsLeft(mBarShadowRectBuffer.right))
continue;

if (!mViewPortHandler.isInBoundsRight(mBarShadowRectBuffer.left))
break;

mBarShadowRectBuffer.top = mViewPortHandler.contentTop();
mBarShadowRectBuffer.bottom = mViewPortHandler.contentBottom();

c.drawRect(mBarShadowRectBuffer, mShadowPaint);
}
}

// initialize the buffer
BarBuffer buffer = mBarBuffers[index];
buffer.setPhases(phaseX, phaseY);
buffer.setDataSet(index);
buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency()));
buffer.setBarWidth(mChart.getBarData().getBarWidth());

buffer.feed(dataSet);

trans.pointValuesToPixel(buffer.buffer);

final boolean isSingleColor = dataSet.getColors().size() == 1;

if (isSingleColor) {
mRenderPaint.setColor(dataSet.getColor());
}

for (int j = 0; j < buffer.size(); j += 4) {

if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
continue;

if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
break;

if (!isSingleColor) {
// Set the color for the currently drawn value. If the index
// is out of bounds, reuse colors.
mRenderPaint.setColor(dataSet.getColor(j / 4));
}

c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mRenderPaint);

if (drawBorder) {
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mBarBorderPaint);
}

Drawable d = getResources().getDrawable(R.drawable.fade_red);
d.setBounds((int)buffer.buffer[j], (int)buffer.buffer[j + 1], (int)buffer.buffer[j + 2],
(int)buffer.buffer[j + 3]);
d.draw(c);
}
}

@Override
public void drawExtras(Canvas c) {
super.drawExtras(c);
/*
Paint p = new Paint();
p.setAlpha(90);

Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.zzang);
c.drawBitmap(image, 0, 0, p);
*/
}
}
}

https://github.com/PhilJay/MPAndroidChart


https://github.com/incree/MPAndroidChart-custom-BarChartRenderer-example












Posted by incree

2018/04/07 07:14 2018/04/07 07:14
, ,
Response
0 Trackbacks , 0 Comments
RSS :
http://www.incree.com/tc/incree/rss/response/389

Trackback URL : 이 글에는 트랙백을 보낼 수 없습니다

Android gravity, layout_gravity dynamic programmatically

gravity : 자식 뷰를 어떻게 표시 할지
layout_gravity : 부모 뷰에 어떻게 표시할지

동적으로 추가할때 layout_gravity는 LayoutParams에 적용해야 하고
gravity는 View에 적용한다




LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.setGravity(Gravity.CENTER);
    setLayoutParams(params);

    setGravity(Gravity.CENTER);

Posted by incree

2018/03/20 12:01 2018/03/20 12:01
, ,
Response
0 Trackbacks , 0 Comments
RSS :
http://www.incree.com/tc/incree/rss/response/388

Trackback URL : 이 글에는 트랙백을 보낼 수 없습니다

안드로이드 웹뷰 액티비티를 사용하고 정상적으로 종료하지 않았을때

fabric log


Crash Insights
Heads Up!
Unable to add window -- token is not valid; is your activity running?

Details:
This crash is usually caused by your app trying to display a dialog using a previously-finished Activity as a context. For example, this can happen if an Activity triggers an AsyncTask that tries to display a dialog when it is finished, but the user navigates back from the Activity before the task is completed.

s crash is usually caused by your app trying to display a dialog using a previously-finished Activity as a context. For example, this can happen if an Activity triggers an AsyncTask that tries to display a dialog when it is finished, but the user navigates back from the Activity before the task is completed.
Resources:
1. Android – Displaying Dialogs From Background Threads
2. Error : BinderProxy@45d459c0 is not valid; is your activity running?

Fatal Exception: android.view.WindowManager$BadTokenException
Unable to add window -- token android.os.BinderProxy@d21dce2 is not valid; is your activity running?
 Raw Text
android.view.ViewRootImpl.setView (ViewRootImpl.java:890)
com.android.webview.chromium.Ap.handleJsAlert (WebViewContentsClientAdapter.java:355)
org.chromium.android_webview.AwContentsClientBridge$$Lambda$2.run (Unknown Source:3)
android.os.Handler.handleCallback (Handler.java:751)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1358)
Show all 44 Threads

이와 같은 에러가 나면서 앱이 크래쉬 되는 경우가 있다.

webview activity를 종료한 후 결제등의 화면에서 세션이 종료되는 것을 알리는 alert를 띄워줄때 발생하는 경우가 있다.

activity만 종료했기 때문이고, webview도 distory 해주면 이 에러는 해결된다.

백버튼이나 액티비티 종료 버튼을 눌러서 종료할때

다음과 같이 webview를 distory 한후 activity를 finish 한다.

@Override
public void onBackPressed() {
webView.destroy();
finish();
}


사용자 삽입 이미지



Posted by incree

2018/01/26 23:16 2018/01/26 23:16
,
Response
0 Trackbacks , 0 Comments
RSS :
http://www.incree.com/tc/incree/rss/response/385

Trackback URL : 이 글에는 트랙백을 보낼 수 없습니다


Android Studio에서 다음지도 샘플예제를 genymotion이나 avd에서 실행하려고 하면 


사용자 삽입 이미지

이와 같은 메시지가 뜨면서 앱이 설치가 되지 않는다.


4:Run 탭의 로그를 보면 아래와 같이 설치할 수 없다는 에러를 확인할 수 있다


04/05 18:41:39: Launching app
$ adb push X:\Android_DaumMap_Sample_1.2.19.0\Android_DaumMap_Sample_1.2.19.0\app\build\outputs\apk\app-debug.apk /data/local/tmp/net.daum.android.map.openapi.sampleapp
$ adb shell pm install -r "/data/local/tmp/net.daum.android.map.openapi.sampleapp"
    pkg: /data/local/tmp/net.daum.android.map.openapi.sampleapp
Failure [INSTALL_FAILED_NO_MATCHING_ABIS]




$ adb shell pm uninstall net.daum.android.map.openapi.sampleapp
$ adb shell pm install -r "/data/local/tmp/net.daum.android.map.openapi.sampleapp"
    pkg: /data/local/tmp/net.daum.android.map.openapi.sampleapp
Failure [INSTALL_FAILED_NO_MATCHING_ABIS]






이럴 경우에는 build.gradle 파일을 수정해서 해결할 수 있다


아래 빨간 내용을 android {} 내에 추가하면 된다.
(INSTALL_FAILED_NO_MATCHING_ABIS 로 구글에서 검색하면 많이 나오는 내용)




build.gradle
...........
android {
...........
...........
splits {
    abi {
        enable true
        reset()
        include 'x86', 'armeabi-v7a'
        universalApk true
    }
}

}


** 네이버, 구글 지도 샘플 예제는 별도의 수정없이 바로 설치 실행 가능하다.

Posted by incree

2017/04/05 18:56 2017/04/05 18:56
Response
0 Trackbacks , 0 Comments
RSS :
http://www.incree.com/tc/incree/rss/response/380

Trackback URL : 이 글에는 트랙백을 보낼 수 없습니다


Daum map에 Custom Marker 넣기

안드로이드앱에 다음 지도를 넣고 지도에 커스텀 마커를 표시하려고 할때

다음에서 제공하는 샘플앱을 그대로 따라하면 에러나면서 앱이 죽어버린다.

로그캣에 알수없는 오류 내용만 뱉어내고 죽기 때문에 오류 내용으로는 원인을 찾기가 어렵다.

샘플앱에 있는 "키워드 장소검색"은 정상 작동하기 때문에 서로 어떤 차이가 있는지 비교해서 오류를 해결했다.


에러가 나는 코드가
mapView.addPOIItem(mCustomMarker);
mapView.selectPOIItem(mCustomMarker, true);

mapView.setMapCenterPoint(CUSTOM_MARKER_POINT, false);


이 부분인데, 오류의 원인은 결론적으로 맵이 초기화 되기 전에 이 메소드들이 호출돼 발생하는 것이었다.


따라서 이 코드들이 맵이 초기화 완료된 후(onMapViewInitialized) 에 호출되도록 수정하면 된다.




다음 샘플앱 소스
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.demo_nested_mapview);
    mMapView = (MapView) findViewById(R.id.map_view);
    mMapView.setDaumMapApiKey(MapApiConst.DAUM_MAPS_ANDROID_APP_API_KEY);
    mMapView.setMapViewEventListener(this);
    mMapView.setPOIItemEventListener(this);

    // 구현한 CalloutBalloonAdapter 등록
    mMapView.setCalloutBalloonAdapter(new CustomCalloutBalloonAdapter());
    createDefaultMarker(mMapView);
    createCustomMarker(mMapView);
    createCustomBitmapMarker(mMapView);
    showAll();
}

@Override
public void onMapViewInitialized(MapView mapView) {

}


이와 같이
createDefaultMarker(mMapView);
    createCustomMarker(mMapView);

    createCustomBitmapMarker(mMapView);
이 메소드들이 onCreate에서 호출하는데

이들을 모두 onMapViewInitialized로 이동하면 된다.


수정된 소스
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.demo_nested_mapview);
    mMapView = (MapView) findViewById(R.id.map_view);
    mMapView.setDaumMapApiKey(MapApiConst.DAUM_MAPS_ANDROID_APP_API_KEY);
    mMapView.setMapViewEventListener(this);
    mMapView.setPOIItemEventListener(this);

    // 구현한 CalloutBalloonAdapter 등록

    mMapView.setCalloutBalloonAdapter(new CustomCalloutBalloonAdapter());
}

@Override

public void onMapViewInitialized(MapView mapView) {
    createDefaultMarker(mMapView);
    createCustomMarker(mMapView);
    createCustomBitmapMarker(mMapView);

    showAll();
}



추가로 라이브러리의 위치가 메뉴얼과 샘플앱이 다르게 표현돼 있는데, 샘플앱과 같은 위치에 두어야 정상작동한다.


샘플앱의 라이브러리 구조
사용자 삽입 이미지




다음 메뉴얼의 라이브러리 구조
http://apis.map.daum.net/android/guide/
사용자 삽입 이미지





그외에 다른 이슈도 있는 것 같은데 다음 url 참조
http://jaysul.blogspot.kr/2015/01/andr ··· %3Fm%3D1




















Posted by incree

2017/03/05 16:26 2017/03/05 16:26
, , , ,
Response
0 Trackbacks , 0 Comments
RSS :
http://www.incree.com/tc/incree/rss/response/378

Trackback URL : 이 글에는 트랙백을 보낼 수 없습니다

정확하게는 재생이 안되는 것이 아니라 재생은 되는데, 화면이 안보일때 해결 방법

webview의 layter type을 softwore로 설정했다면 이를 삭제한다

webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

와 같이 설정한 곳이 있으면 삭제 또는 LAYER_TYPE_HARDWARE  로 변경


LAYER_TYPE_SOFTWARE 는 Android version에 따라서 webview 성능 향상을 위해 사용하라는 의견들이 많다







Posted by incree

2017/02/10 05:49 2017/02/10 05:49
, , , ,
Response
0 Trackbacks , 0 Comments
RSS :
http://www.incree.com/tc/incree/rss/response/377

Trackback URL : 이 글에는 트랙백을 보낼 수 없습니다

[Android] Firebase 로 GCM 구현하기

구글 GCM이 Firebase로 바뀌면서 나중에 참고하기 위해서 정리한다

구글 계정이 있고, Android 프로젝트용

https://firebase.google.com/console/

사용자 삽입 이미지

구글계정이 있고 구글 계정과 연결해서 사용할때 firebase console에서 하단의 '여기를 클릭'을 클릭

사용자 삽입 이미지

Sign in with Google 클릭

사용자 삽입 이미지

허용 클릭

사용자 삽입 이미지

구글 계정으로 연동이 됐으면 다시 firebase console에서 '새 프로젝트 만들기'를 클릭한다

사용자 삽입 이미지

프로젝트 이름, 국가/지역을 선택하고 프로젝트 만들기를 클릭한다

사용자 삽입 이미지

프로젝트가 만들어 지면 프로젝트 화면으로 이동하는데, Notifications를 클릭하면 위 화면이 나온다. 운선 안드로이드를 클릭한다.

사용자 삽입 이미지

패키지 이름을 넣고 앱 추가를 클릭한다. - 중간에 설명처럼 Android Studio 2.2. 이상에서도 가능하다.

사용자 삽입 이미지

이전 단계에서 '앱 추가'를 클릭하면 자동으로 google-services.json이 다운로드 된다. 이 파일을 프로젝트에 추가한다.

사용자 삽입 이미지

gradle 파일을 수정하고 동기화 한 후 완료를 클릭한다
주의 : 2번 앱수순 gradle 파일 수정시 화살표의 'Add to the bottom of the file'를 반드시 지켜야 한다.

사용자 삽입 이미지

완료시 나오는 화면 앱 개발까지 완료되면 '첫 번째 메시지 보내기'를 클릭해서 테스트 하면 된다.

사용자 삽입 이미지

메시지를 발송해 본다



Posted by incree

2016/11/19 02:14 2016/11/19 02:14
, ,
Response
0 Trackbacks , 0 Comments
RSS :
http://www.incree.com/tc/incree/rss/response/371

Trackback URL : 이 글에는 트랙백을 보낼 수 없습니다

구글 클라우드 프린트를 이용해서 웹에 있는 파일(pdf) 인쇄하기

 전체 소스 : GoogleCloudPrintExample.zip




Android Integration
https://developers.google.com/cloud-print/docs/android

Posted by incree

2016/09/17 22:34 2016/09/17 22:34
,
Response
0 Trackbacks , 0 Comments
RSS :
http://www.incree.com/tc/incree/rss/response/369

Trackback URL : 이 글에는 트랙백을 보낼 수 없습니다


Notices

Archives

Authors

  1. incree

Recent Trackbacks

Calendar

«   2018/08   »
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  

Site Stats

Total hits:
478839
Today:
153
Yesterday:
257