728x90

산수이 튜너 TU-717

이 사진은 2019.5.12 일 업로드한 사진

2018.12.30 업로드한 사진


JMLAB 북쉘프 스피커


데논 3805


야모(Jamo) 스피커


해드폰 앰프 Creek OBH-21 SE


'음악 > 오디오' 카테고리의 다른 글

Rega DAC 및 스텔로 U3  (0) 2021.07.07
테드라2 프리앰프  (2) 2019.01.19
하플러 DH 500 파워앰프(명기)  (1) 2019.01.19
블로그 이미지

Link2Me

,
728x90

 

내가 갖고 있었던 인도 관련 서적이다.

어떤 것은 좀 본 것도 있고 아예 안 본 것도 있다.

인도영화에 흠취하여 인도에 대해 좀 더 알고 싶어서 샀던 책이다.

이 책은 카페의 다른 회원에게 보내줘서 현재는 나에게 없다.

블로그 이미지

Link2Me

,
728x90

JSON 데이터 포멧으로 Web URL 데이터를 받아서 PHP 배열로 변환하여 파싱하는 방법이다.


<?php
$url = "http://100.10.10.10/chart/data.json";
$data = file_get_contents_curl($url);

//echo $data.'<br />';

$R = json_decode($data,TRUE);// JSON 데이터를 배열로 변환

foreach($R['content'] as $val) {
    echo $val['sysdate'] . ' | ' . $val['mcount'] . "<br />";
}

function file_get_contents_curl($url) {
    $ch = curl_init();// curl 리소스를 초기화
    curl_setopt($ch, CURLOPT_URL, $url); // url을 설정
    // 헤더는 제외하고 content 만 받음
    curl_setopt($ch, CURLOPT_HEADER, 0);
    // 응답 값을 브라우저에 표시하지 말고 값을 리턴
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $data = curl_exec($ch);
    curl_close($ch);// 리소스 해제를 위해 세션 연결 닫음
    return $data;
}

?>
 


블로그 이미지

Link2Me

,
728x90

MPAndroidChart 라이브러리를 활용한 PieChart 함수 예제다.

라이브러리 추가하는 사항은 http://link2me.tistory.com/1576 게시글을 참조하라.

 <com.github.mikephil.charting.charts.PieChart
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/chart" />

 private void PieChartGraph(ArrayList<String> labelList, ArrayList<Integer> valList) {
    // PieChart 메소드
    PieChart pieChart = (PieChart) findViewById(R.id.chart);

    ArrayList<Entry> entries = new ArrayList<>();
    for(int i=0; i < valList.size();i++){
        entries.add(new Entry((Integer) valList.get(i), i));
    }

    PieDataSet depenses = new PieDataSet (entries, "월별 가입자수");
    depenses.setAxisDependency(YAxis.AxisDependency.LEFT);

    ArrayList<String> labels = new ArrayList<String>();
    for(int i=0; i < labelList.size(); i++){
        labels.add((String) labelList.get(i));
    }

    PieData data = new PieData(labels,depenses); // 라이브러리 v3.x 사용하면 에러 발생함
    depenses.setColors(ColorTemplate.COLORFUL_COLORS); //

    pieChart.setData(data);
    pieChart.animateXY(1000,1000);
    pieChart.invalidate();
}




블로그 이미지

Link2Me

,
728x90

MPAndroidChart 라이브러리를 활용한 BarChart 함수를 만들었다.

라이브러리 추가하는 사항은 http://link2me.tistory.com/1576 게시글을 참조하라.


 <com.github.mikephil.charting.charts.BarChart
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/barchart" />

private void BarChartGraph(ArrayList<String> labelList, ArrayList<Integer> valList) {
    // BarChart 메소드
    BarChart barChart = (BarChart) findViewById(R.id.barchart);

    ArrayList<BarEntry> entries = new ArrayList<>();
    for(int i=0; i < valList.size();i++){
        entries.add(new BarEntry((Integer) valList.get(i), i));
    }

    BarDataSet depenses = new BarDataSet (entries, "전국 가입자수"); // 변수로 받아서 넣어줘도 됨
    depenses.setAxisDependency(YAxis.AxisDependency.LEFT);

    ArrayList<String> labels = new ArrayList<String>();
    for(int i=0; i < labelList.size(); i++){
        labels.add((String) labelList.get(i));
    }

    BarData data = new BarData(labels,depenses); // 라이브러리 v3.x 사용하면 에러 발생함
    depenses.setColors(ColorTemplate.COLORFUL_COLORS); //

    barChart.setData(data);
    barChart.animateXY(1000,1000);
    barChart.invalidate();
}


블로그 이미지

Link2Me

,
728x90

MPAndroidChart 라이브러리를 이용하여 그래프 그리는 걸 테스트하고 있다.

최신버전 라이브러리를 사용하면 X축에 값을 직접 지정하는 걸 구현하기가 쉽지 않은거 같다.

그래서 라이브러리 버전을 낮은 걸 찾아서 추가했더니 에러가 발생하지 않고 그래프가 잘 그려진다.


1. build.gradle

apply plugin: 'com.android.application'


android {

    compileSdkVersion 27


    defaultConfig {

        applicationId "com.tistory.android.mpchart"

        minSdkVersion 15

        targetSdkVersion 27

        versionCode 1

        versionName "1.0"


        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"


    }


    repositories {

        maven { url "https://jitpack.io" }

    }


    buildTypes {

        release {

            minifyEnabled false

            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

        }

    }


}


dependencies {

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


    implementation 'com.android.support:appcompat-v7:27.1.1'

    implementation 'com.android.support.constraint:constraint-layout:1.1.3'

    implementation 'com.android.support:support-v4:27.1.1'

    implementation 'com.android.support:recyclerview-v7:27.1.1' // ListView 개선 버전

    implementation 'com.android.support:cardview-v7:27.1.1'

    implementation 'com.android.support:design:27.1.1'

    implementation 'gun0912.ted:tedpermission:2.0.0'

    implementation 'com.android.volley:volley:1.1.0'

    implementation 'com.github.bumptech.glide:glide:3.8.0' // 이미지 라이브러리

    //implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0-alpha' // 차트 라이브러리

    implementation 'com.github.PhilJay:MPAndroidChart:v2.2.4'

} 


activity_graphview.xml

<?xml version="1.0" encoding="utf-8"?>

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

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical">


       <com.github.mikephil.charting.charts.LineChart

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:id="@+id/chart" />


</LinearLayout> 


3. java 코드

package com.tistory.android.mpchart;


import android.content.Context;

import android.content.Intent;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.util.Log;

import android.view.View;

import android.widget.TextView;


import com.android.volley.Request;

import com.android.volley.RequestQueue;

import com.android.volley.Response;

import com.android.volley.VolleyError;

import com.android.volley.toolbox.StringRequest;

import com.android.volley.toolbox.Volley;

import com.github.mikephil.charting.charts.LineChart;

import com.github.mikephil.charting.components.YAxis;

import com.github.mikephil.charting.data.Entry;

import com.github.mikephil.charting.data.LineData;

import com.github.mikephil.charting.data.LineDataSet;

import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;

import com.github.mikephil.charting.utils.ColorTemplate;


import org.json.JSONArray;

import org.json.JSONException;

import org.json.JSONObject;


import java.util.ArrayList;


public class graphView extends AppCompatActivity implements View.OnClickListener {

    Context context;

    ArrayList<Integer> jsonList = new ArrayList<>(); // ArrayList 선언

    ArrayList<String> labelList = new ArrayList<>(); // ArrayList 선언


    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_graphview);

        context = this.getBaseContext();

        initView();

    }



    private void initView() {

        // button action...

        findViewById(R.id.back_btn).setOnClickListener(this);

        findViewById(R.id.home_btn).setOnClickListener(this);


        // title set

        TextView title = (TextView) this.findViewById(R.id.navibar_text); // title

        //title.setText(getIntent().getExtras().getString("title"));

        title.setText("그래프");


        DataVolley();

    }


    private void DataVolley() {

        // 1. RequestQueue 생성 및 초기화

        RequestQueue requestQueue = Volley.newRequestQueue(context);


        String url = "http://100.10.10.10/chart/data.json";


        // 2. Request Obejct인 StringRequest 생성

        StringRequest request = new StringRequest(Request.Method.GET, url,

                new Response.Listener<String>() {

                    @Override

                    public void onResponse(String response) {

                        //Log.d("result", "[" + response + "]");

                        showJSONList(response);

                    }

                },

                new Response.ErrorListener() {

                    @Override

                    public void onErrorResponse(VolleyError error) {

                        Log.d("error", "[" + error.getMessage() + "]");

                    }

                }) {


        };


        // 3) 생성한 StringRequest를 RequestQueue에 추가

        requestQueue.add(request);

    }


    private void showJSONList(String JSONdata) {

        labelList.clear();

        jsonList.clear();


        try { // 파싱처리 부분은 json 파일 포멧에 맞게 설정해야 한다.

            JSONObject jsonObj = new JSONObject(JSONdata);

            JSONArray jsonArray = jsonObj.getJSONArray("content");

            for (int i = 0; i < jsonArray.length(); i++) {

                JSONObject c = jsonArray.getJSONObject(i);

                final String Sdate = c.getString("sysdate");

                final String Mdata = c.getString("mcount");

                System.out.println(i + " mcount : " + Mdata);

                labelList.add(DateChange(Sdate));

                jsonList.add(Integer.parseInt(Mdata));

            }


        } catch (JSONException e) {

            e.printStackTrace();

        }


        LineChartGraph(labelList, jsonList);

    }


    private void LineChartGraph(ArrayList labelList, ArrayList valList){

        // LineChart 메소드

        LineChart lineChart = (LineChart) findViewById(R.id.chart);


        ArrayList<Entry> entries = new ArrayList<>();

        for(int i=0; i < valList.size();i++){

            entries.add(new Entry((Integer) valList.get(i), i));

        }


        LineDataSet depenses = new LineDataSet(entries, "# of Calls");

        depenses.setAxisDependency(YAxis.AxisDependency.LEFT);


        ArrayList<String> labels = new ArrayList<String>();

        for(int i=0; i < labelList.size(); i++){

            labels.add((String) labelList.get(i));

        }


        ArrayList<ILineDataSet> dataSets = new ArrayList<>();

        dataSets.add((ILineDataSet)depenses);

        LineData data = new LineData(labels,dataSets); // 라이브러리 v3.x 사용하면 에러 발생함

        depenses.setColors(ColorTemplate.COLORFUL_COLORS); //

        //depenses.setDrawCubic(true); //선 둥글게 만들기

        //depenses.setDrawFilled(true); //그래프 밑부분 색칠


        lineChart.setData(data);

        lineChart.animateXY(1000,1000);

        lineChart.invalidate();

    }


    private String DateChange(String sysdate){

        String year = sysdate.split("-")[0];

        String month = sysdate.split("-")[1];

        String day = sysdate.split("-")[2];


        StringBuilder finalString = new StringBuilder();

        finalString.append(year.substring(2,4));

        finalString.append(".");

        finalString.append(month);

        //finalString.append(".");

        //finalString.append(day);

        return finalString.toString();

    }


    @Override

    public void onClick(View view) {

        switch (view.getId()) {

            case R.id.back_btn:

                finish();

                overridePendingTransition(R.anim.rightin, R.anim.rightout);

                break;

            case R.id.home_btn:

                Intent intent = new Intent(graphView.this, MainActivity.class);

                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

                startActivity(intent);

                break;

            default:

                break;

        }

    }


} 


블로그 이미지

Link2Me

,
728x90

Android 에서 엑셀 파일 내보내기를 테스트하고 적어둔다.


테스트 환경 : Android 8.0, Android Studio 3.2.1


1. 엑셀 라이브러리 추가하기

    - http://poi.apache.org/download.html#POI 에서 POI(Binary Distribution) 최신 버전을 다운로드 한다.

    - zip 파일을 받은 걸 압축을 풀면 poi-4.0.1.jar 파일이 보인다.

    - 이 파일을 해당 프로젝트의 libs 폴더에 복사한다.

apply plugin: 'com.android.application'

android {
    compileSdkVersion 27

    defaultConfig {
        applicationId "com.tistory.android.excel"
        minSdkVersion 19
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

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

}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.android.support:support-v4:27.1.1'
    implementation 'com.android.support:recyclerview-v7:27.1.1' // ListView 개선 버전
    implementation 'com.android.support:cardview-v7:27.1.1'
    implementation 'com.android.support:design:27.1.1'
    implementation 'gun0912.ted:tedpermission:2.0.0'
    implementation 'com.android.volley:volley:1.1.0'
    implementation 'com.github.bumptech.glide:glide:3.8.0' // 이미지 라이브러리
    implementation files('libs/poi-4.0.1.jar')
}


2. 컴파일 에러 발생

    Invoke-customs are only supported starting with android 0 --min-api 26

  

    구글링 검색 결과 build.gradle 에 아래 코드 추가 (Java 버전에 맞게 추가 필요)

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }


3. 파일 내보내기 에러 발생

android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.tistory.android.excel/files/test.xls exposed beyond app through ClipData.Item.getUri()


해결방안

- Android Manifest.xml 파일에 아래 provider 코드를 추가한다.

- res/xml/provider_paths.xml 파일을 생성한다.

- Java 코드를 아래와 같이 추가한다.

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

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"
                tools:replace="android:resource" />
        </provider>

    </application>

</manifest>

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="excel" path="." />
</paths>

if (Build.VERSION.SDK_INT >= 24) { // Android Nougat ( 7.0 ) and later
    Uri uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileprovider",xlsFile);
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setDataAndType(uri, "application/excel");
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.putExtra(Intent.EXTRA_STREAM,uri);
    startActivity(Intent.createChooser(intent,"엑셀 내보내기"));
} else {
    Uri uri = Uri.fromFile(xlsFile);
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setType("application/excel");
    intent.putExtra(Intent.EXTRA_STREAM,uri);
    startActivity(Intent.createChooser(intent,"엑셀 내보내기"));
}

// 미디어 스캐닝 (폴더내에 생성된 파일 보이도록 하는 코드)
MediaScannerConnection.scanFile(getApplicationContext(), new String[]{xlsFile.getAbsolutePath()}, null, new MediaScannerConnection.OnScanCompletedListener() {
    @Override
    public void onScanCompleted(String s, Uri uri) {
    }
});
 


구글링으로 찾은 코드가 Android Nougat(7.0 이상)에서 에러가 발생하여 안드로이드 7.0 이상에서 에러 해결 코드로 보완을 했다.

셀 파일 저장 로직은 동일하지만 다른 코드들은 다르다는 걸 알 수 있을 것이다.


테스트에 사용된 전체 코드

package com.tistory.android.excel;

import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.media.MediaScannerConnection;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;

import com.gun0912.tedpermission.PermissionListener;
import com.gun0912.tedpermission.TedPermission;
import com.tistory.android.common.BackPressHandler;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    Context context;
    ArrayList<String> aryName = new ArrayList<>();
    ArrayList<String> aryAge = new ArrayList<>();

    String exportFolderName = "/DCIM/Excel";
    String outputFileName = "test.xls";
    File xlsFile;

    private BackPressHandler backPressHandler;

    PermissionListener permissionlistener = new PermissionListener() {
        @Override
        public void onPermissionGranted() {
            initView();
        }

        @Override
        public void onPermissionDenied(ArrayList<String> deniedPermissions) {
            Toast.makeText(MainActivity.this, "권한 허용을 하지 않으면 서비스를 이용할 수 없습니다.", Toast.LENGTH_SHORT).show();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = this.getBaseContext();
        backPressHandler = new BackPressHandler(this); // 뒤로 가기 버튼 이벤트

        // 네트워크 연결상태 체크
        if (NetworkConnection() == false) NotConnected_showAlert();
        checkPermissions();
    }

    private void checkPermissions() {
        if (Build.VERSION.SDK_INT >= 23) { // 마시멜로(안드로이드 6.0) 이상 권한 체크
            TedPermission.with(context)
                    .setPermissionListener(permissionlistener)
                    .setRationaleMessage("앱을 이용하기 위해서는 접근 권한이 필요합니다")
                    .setDeniedMessage("앱에서 요구하는 권한설정이 필요합니다...\n [설정] > [권한] 에서 사용으로 활성화해주세요.")
                    .setPermissions(new String[]{
                            //android.Manifest.permission.READ_PHONE_STATE,
                            //android.Manifest.permission.CALL_PHONE,  // 전화걸기 및 관리
                            //android.Manifest.permission.WRITE_CONTACTS, // 주소록 액세스 권한
                            android.Manifest.permission.READ_EXTERNAL_STORAGE,
                            android.Manifest.permission.WRITE_EXTERNAL_STORAGE // 기기, 사진, 미디어, 파일 엑세스 권한
                            //android.Manifest.permission.RECEIVE_SMS //, // 문자 수신
                            //android.Manifest.permission.CAMERA
                    })
                    .check();

        } else {
            initView();
        }
    }

    private void initView() {
        initData(); // 읽어온 데이터라고 가정하고 데이터 생성

        FloatingActionButton fab =  findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                saveExcel();
            }
        });
    }

    private void initData(){ // 엑셀에 저장여부만 확인 목적으로 간단하게 추가하는 코드로 작성
        aryName.add("강감찬"); aryAge.add("23");
        aryName.add("이순신"); aryAge.add("57");
        aryName.add("홍길동"); aryAge.add("34");
        aryName.add("이방원"); aryAge.add("53");
        aryName.add("고주몽"); aryAge.add("73");
        aryName.add("유관순"); aryAge.add("68");
    }

    private void saveExcel(){
        Workbook workbook = new HSSFWorkbook();
        Sheet sheet = workbook.createSheet(); // 새로운 시트 생성
        Row row = sheet.createRow(0); // 새로운 행 생성
        Cell cell;

        cell = row.createCell(0); // 1번 셀 생성
        cell.setCellValue("이름"); // 1번 셀 값 입력

        cell = row.createCell(1); // 2번 셀 생성
        cell.setCellValue("나이"); // 2번 셀 값 입력

        cell = row.createCell(2); // 3번 셀 생성
        cell.setCellValue("전화번호"); // 3번 셀 값 입력

        for(int i = 0; i < aryName.size() ; i++){ // 데이터 엑셀에 입력
            row = sheet.createRow(i+1);

            cell = row.createCell(0);
            cell.setCellValue(aryName.get(i));

            cell = row.createCell(1);
            cell.setCellValue(aryAge.get(i));
        }

        // 저장할 폴더 및 파일명
        File xlsPath = new File(Environment.getExternalStorageDirectory() + exportFolderName);
        if (! xlsPath.exists())
            xlsPath.mkdirs(); // 디렉토리가 없으면 생성
        xlsFile = new File(xlsPath, outputFileName);
        if (xlsFile.exists()) { // 기존 파일 존재시 삭제
            xlsFile.delete();
        }

        try{
            FileOutputStream os = new FileOutputStream(xlsFile);
            workbook.write(os); // 지정된 외부 저장소에 엑셀 파일 생성
        }catch (IOException e){
            e.printStackTrace();
        }
        Toast.makeText(getApplicationContext(),xlsFile.getAbsolutePath()+"에 저장되었습니다",Toast.LENGTH_SHORT).show();

        if (Build.VERSION.SDK_INT >= 24) { // Android Nougat ( 7.0 ) and later
            Uri uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileprovider",xlsFile);
            Intent intent = new Intent(Intent.ACTION_SEND);
            intent.setDataAndType(uri, "application/excel");
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.putExtra(Intent.EXTRA_STREAM,uri);
            startActivity(Intent.createChooser(intent,"엑셀 내보내기"));
        } else {
            Uri uri = Uri.fromFile(xlsFile);
            Intent intent = new Intent(Intent.ACTION_SEND);
            intent.setType("application/excel");
            intent.putExtra(Intent.EXTRA_STREAM,uri);
            startActivity(Intent.createChooser(intent,"엑셀 내보내기"));
        }

        // 미디어 스캐닝
        MediaScannerConnection.scanFile(getApplicationContext(), new String[]{xlsFile.getAbsolutePath()}, null, new MediaScannerConnection.OnScanCompletedListener() {
            @Override
            public void onScanCompleted(String s, Uri uri) {
            }
        });


    }

    private void NotConnected_showAlert() {
        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        builder.setTitle("네트워크 연결 오류");
        builder.setMessage("사용 가능한 무선네트워크가 없습니다.\n" + "먼저 무선네트워크 연결상태를 확인해 주세요.")
                .setCancelable(false)
                .setPositiveButton("확인", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        finish(); // exit
                        //application 프로세스를 강제 종료
                        android.os.Process.killProcess(android.os.Process.myPid());
                    }
                });
        AlertDialog alert = builder.create();
        alert.show();
    }

    private boolean NetworkConnection() {
        int[] networkTypes = {ConnectivityManager.TYPE_MOBILE, ConnectivityManager.TYPE_WIFI};
        try {
            ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            for (int networkType : networkTypes) {
                NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
                if (activeNetwork != null && activeNetwork.getType() == networkType) {
                    return true;
                }
            }
        } catch (Exception e) {
            return false;
        }
        return false;
    }

} 


참조한 블로그 글

http://liveonthekeyboard.tistory.com/148


참조하면 도움되는 Intent 내용

http://gogorchg.tistory.com/entry/Android%ED%8E%8C%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-Intent-%EC%82%AC%EC%9A%A9%EB%B2%95


블로그 이미지

Link2Me

,
728x90

Android Graph 그리는 걸 테스트 해보고 있다.


http://www.android-graphview.org/ 에서 제공하는 라이브러리를 이용하여 그래프를 그리는 방법이다.

위 사이트에 가면 쉽게 예제코드를 복사해서 사용할 수 있도록 되어 있다.

JSON 으로 받은 데이터를 직접 대입하는 방법으로 테스트한 결과를 확인해봤다.

X축을 값으로 대체하여 넣은 방법이 없는 것인지 아직 내가 파악을 못한 것인지 몰라도 이 부분은 약간 불편하다.


build.gradle

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

    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.android.support:support-v4:27.1.1'
    implementation 'com.android.support:recyclerview-v7:27.1.1' // ListView 개선 버전
    implementation 'com.android.support:cardview-v7:27.1.1'
    implementation 'com.android.support:design:27.1.1'
    implementation 'gun0912.ted:tedpermission:2.0.0'
    implementation 'com.android.volley:volley:1.1.0'
    implementation 'com.github.bumptech.glide:glide:3.8.0' // 이미지 라이브러리
    implementation 'com.jjoe64:graphview:4.2.2' // 그래프 라이브러리
}


XML Layout

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

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="5"
        >
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            >
            <ImageView
                android:id="@+id/navibar_bg"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:src="@drawable/navibar_bg"
                android:adjustViewBounds="false"
                android:scaleType="fitXY"
                />

            <TextView
                android:id="@+id/navibar_text"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:textColor="@android:color/white"
                android:textSize="22dp"
                android:text="No Title"
                android:singleLine="true"
                />

            <Button
                android:id="@+id/back_btn"
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_centerVertical="true"
                android:layout_marginLeft="10dp"
                android:background="@drawable/btn_back_c" />

            <Button
                android:id="@+id/home_btn"
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginRight="10dp"
                android:background="@drawable/btn_home_c" />

        </RelativeLayout>

        <com.jjoe64.graphview.GraphView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/graph" />

    </LinearLayout>

</LinearLayout>


Java 코드

graphView Class 생성시 GraphView 로 생성하면 에러가 발생한다.


import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.jjoe64.graphview.GraphView;
import com.jjoe64.graphview.ValueDependentColor;
import com.jjoe64.graphview.series.BarGraphSeries;
import com.jjoe64.graphview.series.DataPoint;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;

public class graphView extends AppCompatActivity implements View.OnClickListener  {
    Context context;

    // ArrayList 선언
    ArrayList<Integer> jsonList = new ArrayList<>();

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

    private void initView() {
        // button action...
        findViewById(R.id.back_btn).setOnClickListener(this);
        findViewById(R.id.home_btn).setOnClickListener(this);

        // title set
        TextView title = (TextView) this.findViewById(R.id.navibar_text); // title
        title.setText(getIntent().getExtras().getString("title"));

        DataVolley();
    }

    private void DataVolley() {
        // 1. RequestQueue 생성 및 초기화
        RequestQueue requestQueue = Volley.newRequestQueue(context);

        String url = "http://100.100.100.100/chart/data.json";

        // 2. Request Obejct인 StringRequest 생성
        StringRequest request = new StringRequest(Request.Method.GET, url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        //Log.d("result", "[" + response + "]");
                        showJSONList(response);
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Log.d("error", "[" + error.getMessage() + "]");
                    }
                }) {

        };

        // 3) 생성한 StringRequest를 RequestQueue에 추가
        requestQueue.add(request);
    }

    private void showJSONList(String JSONdata) {

        try {
            JSONObject jsonObj = new JSONObject(JSONdata);
            JSONArray jsonArray = jsonObj.getJSONArray("content");
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject c = jsonArray.getJSONObject(i);
                final String Sdate = c.getString("sysdate");
                final String Mdata = c.getString("mcount");
                //System.out.println(i + " mcount : " + Mdata);
                jsonList.add(Integer.parseInt(Mdata));
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }

        // http://www.android-graphview.org/bar-chart/
        GraphView graph = (GraphView) findViewById(R.id.graph);
        BarGraphSeries<DataPoint> series = new BarGraphSeries<>(new DataPoint[] {
                new DataPoint(0, jsonList.get(0)),
                new DataPoint(1, jsonList.get(1)),
                new DataPoint(2, jsonList.get(2)),
                new DataPoint(3, jsonList.get(3)),
                new DataPoint(4, jsonList.get(4)),
                new DataPoint(5, jsonList.get(5)),
                new DataPoint(6, jsonList.get(6)),
                new DataPoint(7, jsonList.get(7))
        });
        graph.addSeries(series);

        // styling
        series.setValueDependentColor(new ValueDependentColor<DataPoint>() {
            @Override
            public int get(DataPoint data) {
                return Color.rgb((int) data.getX()*255/4, (int) Math.abs(data.getY()*255/6), 100);
            }
        });

        series.setSpacing(50);

        // draw values on top
        series.setDrawValuesOnTop(true);
        series.setValuesOnTopColor(Color.RED);
    }


    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.back_btn:
                finish();
                overridePendingTransition(R.anim.rightin, R.anim.rightout);
                break;
            case R.id.home_btn:
                Intent intent = new Intent(graphView.this, MainActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
                startActivity(intent);
                break;
            default:
                break;
        }
    }
}


블로그 이미지

Link2Me

,
728x90

Bootstrap 그래프 샘플을 가지고 테스트한 걸 적어둔다.


var loadJSON = './test.json';
$.getJSON(loadJSON, function(data){
    $each(data, function(i, item){
        console.log(item.name);
    });
});


사이트에 나온 실제 그래프 그려주는 예제에 위 코드를 적용하여 만들면 아래와 같다.

<script>
var ctx = document.getElementById("myChart").getContext('2d');
var loadJSON = './graph.json'; // 서버에서 제공하는 데이터
$.getJSON(loadJSON, function(data){
    var names = new Array();
    var datas = new Array();
    $.each(data, function(i,item){
        names.push(item.name);
        datas.push(item.data);
    });
    console.log(names);
    console.log(datas);

    var myChart = new Chart(ctx, {
    type: 'bar',
    data: {
      labels: names, // JSON 파일을 읽어서 배열로 저장하여 처리
      datasets: [{
        label: '가입자수',
        data: datas, // JSON 파일을 읽어서 배열로 저장하여 처리
        backgroundColor: [
          'rgba(255, 99, 132, 0.2)',
          'rgba(54, 162, 235, 0.2)',
          'rgba(255, 206, 86, 0.2)',
          'rgba(75, 192, 192, 0.2)',
          'rgba(153, 102, 255, 0.2)',
          'rgba(153, 102, 255, 0.2)',
          'rgba(255, 159, 64, 0.2)'
        ],
        borderColor: [
          'rgba(255,99,132,1)',
          'rgba(54, 162, 235, 1)',
          'rgba(255, 206, 86, 1)',
          'rgba(75, 192, 192, 1)',
          'rgba(153, 102, 255, 1)',
          'rgba(153, 102, 255, 1)',
          'rgba(255, 159, 64, 1)'
        ],
        borderWidth: 1
      }]
    },
    options: {
      scales: {
        yAxes: [{
          ticks: {
            beginAtZero: true
          }
        }]
      }
    }
    });
});
</script>
 


'Web 프로그램 > js, jQuery' 카테고리의 다른 글

jQuery Paging 처리 (진행중....)  (0) 2019.01.20
JSON.parse(), JSON.stringify()  (0) 2019.01.13
jQuery parent, children, find 차이  (0) 2018.12.14
jQuery on 이벤트  (0) 2018.12.10
[Javascript] 화면 크기  (0) 2018.12.07
블로그 이미지

Link2Me

,
728x90

UiView 에 대한 기초적인 내용을 공부하고 적어둔다.


Xcode 상에서 UIView 를 추가하는 그림



//

//  ViewController.m

//  AppView

//

//  Created by jsk005 on 2018. 12. 17..

//  Copyright © 2018 mchello. All rights reserved.

//


#import "ViewController.h"


@interface ViewController ()


@end


@implementation ViewController


- (void)viewDidLoad {

    [super viewDidLoad];

    

    // UIView 생성

    // [[객체타입 alloc]객체에 따른 생성 방법]

    // [[UIView alloc] initWithFrame:사각형]

    // [parent addSubView:child]; // 화면에 추가하기

    // [child removeFromSuperview]; // 화면에서 삭제하기

    

    // 화면에 보이는 것들의 기본 속성 : 사각형

    // CGRect

    // iOS 좌표계는 좌측 상단이 기준점이다.

    CGRect testRect = CGRectMake(10, 10, 100, 100); // x, y, width, height

    UIView *testView1 = [[UIView alloc] initWithFrame:testRect];

    testView1.backgroundColor = [UIColor redColor];

    [self.view addSubview:testView1];

    

    

    UIView *testView2 = [[UIView alloc] initWithFrame:CGRectMake(50, 150, 100, 100)];

    testView2.backgroundColor = [UIColor blueColor];

    [self.view addSubview:testView2];

    

    // 화면에 추가된 view 삭제하기

    //[testView1 removeFromSuperview];

    

    UIView *testView3 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 30)];

    testView3.backgroundColor = [UIColor redColor];

    [testView2 addSubview:testView3]; // UIView 상에다가 추가하기

    

    // 화면에서 숨기기

    //testView1.hidden = YES;

    testView2.hidden = NO; // YES 설정하면 testView3 같이 안보이게 된다.

    

    // 투명도

    testView1.alpha = 0.3; // alpha 0 hidden YES 같다.

    // hidden fade in, fade out 효과를 없다.

    

}


- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}


@end 


실행결과 


'iOS > Objective-C' 카테고리의 다른 글

objective-c 객체 Type  (0) 2018.12.15
objective-c 함수  (0) 2018.12.12
objective C 변수 타입  (0) 2018.12.09
NSLog  (0) 2018.03.01
모바일 Web을 위한 아이콘 변환 사이트  (0) 2017.05.24
블로그 이미지

Link2Me

,
728x90

jQuery 기능을 익히고자 파싱 테스트를 해봤다.

크롬브라우저에서 시도하면 https://brunch.co.kr/@adrenalinee31/1 에서 2. 외부요청을 가능하게 해주는 플러그인 설치를 하면 파싱이 잘 된다.

원하는 조건의 selector 를 찾느라고 좀 삽질을 했다.

$(html).find('.wiki-heading').find("a:contains('3.2.')").parent().next().find(".wiki-link-internal")



<!DOCTYPE html>

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>

<script>
var weburl ='https://namu.wiki/w/KBO%20%EB%A6%AC%EA%B7%B8/2018%EB%85%84/%EC%8B%A0%EC%9D%
B8%EB%93%9C%EB%9E%98%ED%94%84%ED%8A%B8'

$.get(weburl, function( html ) {
    var data = new Array();
    // 찾으려는 className 을 반복적으로 찾는다.
    var heading = $(html).find('.wiki-heading').find("a:contains('3.2.')").text();
    //console.log(heading);
    var nextclass = $(html).find('.wiki-heading').find("a:contains('3.2.')").parent().next().find(".wiki-link-internal");
    $(html).find('.wiki-heading').find("a:contains('3.2.')").parent().next().find(".wiki-link-internal").each( function(){
        var text = $(this).parent().text();
        if(text !== 'kt' && text !== '삼성' && text !== '롯데' && text !== '한화' && text !== 'SK' && text !== 'KIA' && text !== 'LG' && text !== 'NC' && text !== '넥센' && text !== '두산') {
            //console.log(text);
            data.push(text);
        }
    });

    for(var i=0;i<data.length;i++){
        console.log(data[i]);
    }
});
</script>

</body>
</html>



파싱 결과


크롬 브라우저 콘솔상에서 연습해보던 Javascript 코드

var data = document.querySelectorAll('.wiki-table-wrap .wiki-table .wiki-link-internal');
for(var i=0;i<data.length;i++){
    var t = data[i];
    t = t.innerText;
    console.log(t);
}


블로그 이미지

Link2Me

,
728x90

//

//  ViewController.m

//  object_make

//

//  Created by jsk005 on 2018. 12. 13..

//  Copyright © 2018 . All rights reserved.

//


#import "ViewController.h"


@interface ViewController ()


@end


@implementation ViewController


- (void)viewDidLoad {

    [super viewDidLoad];

    // 객체 : Alloc -> Init

    // 1. [[객체타입 alloc] 객체에 따른 생성 방법]

    // 2. [객체타입 객체에 따른 생성 방법]

    // 객체타입 *객체명 =

    

    // NSString

    NSString *myName = [[NSString alloc] initWithFormat:@"link2me."];

    NSLog(@"My Name is %@", myName);

    

    NSString *myCarName = [NSString stringWithFormat:@"New Pride."];

    NSLog(@"My CarName is %@", myCarName);

    

    // NSNumber

    NSNumber *myAge = [[NSNumber alloc] initWithInteger:33];

    NSLog(@" 나이 : %@", myAge);

    

    NSInteger changeAge = [myAge integerValue];

    NSLog(@"Integer 형식 변환 : %li",changeAge);

    

    NSNumber *myScore = [[NSNumber alloc] initWithFloat:89.53];

    NSLog(@" 수학점수 : %@", myScore);

    

    CGFloat changValue = [myScore floatValue];

    NSLog(@"Float 형식 변환 : %f", changValue);

    

}

- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}


@end


'iOS > Objective-C' 카테고리의 다른 글

objective-c UIView 기초  (0) 2018.12.17
objective-c 함수  (0) 2018.12.12
objective C 변수 타입  (0) 2018.12.09
NSLog  (0) 2018.03.01
모바일 Web을 위한 아이콘 변환 사이트  (0) 2017.05.24
블로그 이미지

Link2Me

,
728x90

<div class="box">
   <div class="something1"></div>
   <div class="something2">
      <a class="mylink">My link</a>
   </div>
</div>


$(".mylink").click(function() { // 아래 4개는 모두 동일한 결과 반환
    $(this).parent().siblings(".something1");
    $(this).parent().prev(); // if you always want the parent's previous sibling
    $(this).parents(".box").children(".something1");

    $(this).closest('.box').children('.something1');

});


- closest()는 모든 부모 요소를 대상으로하여 원하는 요소만 선택자로 가져올 수 있다.
- 하나가 아닌 모든 부모 요소를 반환할 필요가 있다면 parents() 메소드를 사용한다.
- parent()는 해당 요소의 바로 위의 부모 요소를 반환한다.

- children()은 해당 요소의 바로 아래 자식 요소들만을 반환한다.

- find()는 해당 노드 아래의 전체 DOM을 탐색하여 반환한다.

- prev() - 이전 요소를 선택하도록 반환한다.
- next() - 다음 요소를 선택하도록 반환한다.




'Web 프로그램 > js, jQuery' 카테고리의 다른 글

JSON.parse(), JSON.stringify()  (0) 2019.01.13
JSON 데이터 읽어서 그래프 그리기  (0) 2018.12.18
jQuery on 이벤트  (0) 2018.12.10
[Javascript] 화면 크기  (0) 2018.12.07
Javascript 객체 배열  (0) 2018.11.17
블로그 이미지

Link2Me

,

objective-c 함수

iOS/Objective-C 2018. 12. 12. 17:47
728x90

Objective-C 함수에 대해 간략하게 적어둔다.


- (return Type) 함수이:(Type)parameter1, 별칭:(Type) parameter2,... , 별칭:(Type) parametern

   {

        // 함수 body

   }



#import "ViewController.h"


@interface ViewController ()


@end


@implementation ViewController


// 함수

/* 리턴값이 없고 매개변수도 없는 함수

 - (void) 함수명 {

   do something ...

 }

 */

// 함수 호출

// [self 함수명];


/*

 // 매겨변수는 있고 리턴값은 없는 함수

 - (return Type) 함수명 : (매개변수 타입) 매겨변수명1

   두번째 값에 대한 설명:(매개변수 타입) 매겨변수명2

 {

    return Type 있으면 return returnValue;

    return Type 없으면 , void 리턴이 없음.

 }

 */


- (void) sumFunction1 : (NSInteger) firstValue {

    NSLog(@" 더하기 = %li", firstValue + 10);

}


- (void) sumFunction2 : (NSInteger) firstValue

      withValue:(NSInteger) secondValue

{

    NSLog(@"firsrtValue + secondValue = %li", firstValue + secondValue);

}


- (NSInteger) sumFunction3 : (NSInteger) firstValue

                  withValue:(NSInteger) secondValue

{

    NSInteger returnValue = firstValue + secondValue;

    return returnValue;

}


- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    

    // 함수에서 원하는 매개변수의 타입과 내가 함수를 호출하면서 넣어주는 값의 타입을 맞춰야 한다.

    [self sumFunction1:30];

    

    [self sumFunction2:10 withValue:30];

    

    NSLog(@"리턴값이 있는 함수 결과 : %li", [self sumFunction3:10 withValue:30]);

    

    }


- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}


@end



'iOS > Objective-C' 카테고리의 다른 글

objective-c UIView 기초  (0) 2018.12.17
objective-c 객체 Type  (0) 2018.12.15
objective C 변수 타입  (0) 2018.12.09
NSLog  (0) 2018.03.01
모바일 Web을 위한 아이콘 변환 사이트  (0) 2017.05.24
블로그 이미지

Link2Me

,
728x90

jQuery on 함수는 1.7버전부터 추가 되었다.
.on( events [, selector ] [, data ], handler(eventObject) )
 - event : 등록하고자 하는 이벤트 타입을 지정한다. (예: "click") s가 붙었으니 여러개도 사용가능하다.
 - selector : 이벤트가 설치된 엘리먼트의 하위 엘리먼트를 이벤트 대상으로 필터링한다.
 - data : 이벤트가 실행될 때 핸들러로 전달될 데이터를 설정한다.
 - handler : 이벤트 핸들러 함수

$(elem).on("click focus keydown", function(e) { ... });

on 함수의 종료는 off 함수가 있다.

'Web 프로그램 > js, jQuery' 카테고리의 다른 글

JSON 데이터 읽어서 그래프 그리기  (0) 2018.12.18
jQuery parent, children, find 차이  (0) 2018.12.14
[Javascript] 화면 크기  (0) 2018.12.07
Javascript 객체 배열  (0) 2018.11.17
[jQuery] HTML 속성의 제어  (0) 2018.11.15
블로그 이미지

Link2Me

,
728x90

윈도우/맥북에서 동시에 사용할 수 있는 Editor를 찾다보니 Brackets 이 괜찮은 거 같아서 이용을 해보고 있다.


새로운 파일을 생성하고 Shift + Tab 키를 누르니까 HTML5 기본 포멧이 바로 생성된다.

들여쓰기는 보통은 Shift + Tab 키인데, brackets 에서는 Ctrl + [ 키를 누르면 된다.

내어쓰기는 보통은 Tab 인데, brackets 에서는 Ctrl + ] 키를 누르면 된다.

블로그 이미지

Link2Me

,
728x90

//
//  main.m
//  Hello
//
//  Created by jsk005 on 2018. 12. 7..
//  Copyright (c) 2018년 link2me. All rights reserved.
//

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
       
        // 변수타입 변수명 = 값;
        // 변수명은 영어, 숫자, 정해진 특수문자(_ $)로만 작성한다.
        // 변수명은 가장앞에 숫자는 올 수 없다.
        // 변수명에 예약어는 사용할 수 없다.
        // 실제 변수명은 읽었을 때 이해가 되는 변수명을 사용하자.
       
        // 정수형 변수 타입 NSInterger, NSUInterger
        NSInteger myAge = 36;
        NSInteger myCarNo = 9560;
       
        NSLog(@"현재 나이 : %li",myAge);
        NSLog(@"내차번호 : %li", myCarNo);
       
        // 실수형 변수 타입 CGFloat
        CGFloat curTemperature = 36.5;
        CGFloat myWeight = 73.5;
       
        NSLog(@"현재 온도 : %f", curTemperature);
        NSLog(@"내 몸무게 : %f", myWeight);
       
        // BOOL 타입 변수 : YES(1), NO(0)
        BOOL isChild = YES;
        BOOL isWoman = NO;
       
        NSLog(@"아이입니까? : %li", isChild);
        NSLog(@"여자입니까? : %li", isWoman);


        // 사칙연산

        

        NSInteger a = 5;

        NSInteger b = 10;

        NSInteger c = a + b;

        

        NSLog(@"a - b = %li", a - b);

        NSLog(@"c value : %li", c);

        

        // 타입 캐스팅 : 미리 계산하기 전에 타입 캐스팅을 해줘야 한다.

        NSLog(@"a / b = %f", (CGFloat)a / (CGFloat)b);

        

        CGFloat myGrade = 87.5;

        CGFloat yourGrade = 90.3;

        CGFloat sumGrade = myGrade + yourGrade;

        

        NSLog(@"sumGrade = %.3f",sumGrade);

       
    }
    return 0;
}

'iOS > Objective-C' 카테고리의 다른 글

objective-c UIView 기초  (0) 2018.12.17
objective-c 객체 Type  (0) 2018.12.15
objective-c 함수  (0) 2018.12.12
NSLog  (0) 2018.03.01
모바일 Web을 위한 아이콘 변환 사이트  (0) 2017.05.24
블로그 이미지

Link2Me

,
728x90

서울시가 추진중인 광화문 복합역 구상안

서울시가 세종대로 지하에 광화문 복합역을 만들고 이곳에 최소 6개 노선이 지나게 한다는 구상을 6일 밝혔다. 광화문복합역은 시가 2021년 준공을 목표로 추진 중인 ‘새로운 광화문광장’ 조성 사업의 일환이다.


서울시는 광화문이 신설되면 역사 추가에 따른 공사비만 1000억원, 해당 역에 상가·문화시설·보행로 등을 완비하는 데는 총 2500억원이 들 것으로 추산했다.


서울시는 GTX-A 노선에 광화문복합역 추가를 위한 타당성 조사와 기본계획 수립에 필요한 예산 10억원을 시의회에 상정했다. 해당 예산이 14일 예결특위를 거쳐 20일 본회의에서 의결되면 시는 곧바로 타당성 용역 발주한다는 방침이다.


국토부는 광화문이 당초 GTX-A의 기본계획에 포함되지 않았고, 서울시 사업이므로 역 추가에 따른 비용은 모두 시가 부담해야 한다는 입장을 고수해왔다. 하지만 서울시는 타당성 조사를 통해 추가 비용과 수익 규모 등을 면밀히 검토한 뒤 국비와 시비 분담 기준을 정하겠다는 입장이다. 서울시 관계자는 “통상 광역철도 건설에는 국비와 시비를 6대 4의 비율로 분담하는데, 광화문복합역 신설 비용도 이 같은 기준에 따를 것으로 기대한다”고 말했다.

신분당선 : 광교 - 성복 - 수지 - 동천 - 미금 - 정자 - 판교 - 청계산 입구 - 양재시민의 숲 - 양재 - 강남 --- 신사

              동빙고 - 국립박물관 - 용산 - 시청 - 상명대 - 독바위 - 은평뉴타운 - 삼송


GTX-B 노선은 2019년 상반기 중에 나올 것으로 예상하고 있다.
2025년 개통을 목표로 사업이 추진된다. 총 사업비는 5조9천억원 정도이다.



파주~수서 구간은 하루 132회(편도 기준)를 운행하고, 파주~동탄 구간은 이보다 적은 100회만 운행할 예정이다.
수서~동탄 구간에서 GTX의 운행횟수가 줄어든 것은 수서와 동탄 사이 고속선로를 수서고속철도(SR)와 나눠서 써야 하기 때문이다. 수서~동탄 고속선로의 용량은 하루 184회로 이 중 60회가 SR 몫이다.

파주~수서 노선은 GTX 전용이어서 상대적으로 사용 가능한 용량이 크다.
총 사업비는 3조 원대며 착공에서 완공까지는 5년가량 걸린다. (완공 예상시기 : 2024년 또는 2025년)

철도업계 관계자는 "실시협약을 체결하고도 착공까지는 대개 1년 넘게 걸린다. GTX-A도 아무리 절차를 빨리 진행한다고 해도 내년(2019) 중반 이전에 착공은 불가능할 것"이라고 예상했다.

삼성~동탄 구간도 당초 계획대로 2021년 개통하긴 어렵다는 전망이 나온다.

시청역 추가 설치는 서울시가 요구 중인 것으로 전해진다. 하지만 신한은행 측 계획에는 없는 사안이라 만일 역을 추가할 경우 1900억원가량 되는 건설비를 누가 부담할지가 논란이다.

GTX의 배차간격과 요금, 환승 할인 등이 관건이지만, 역세권 아파트 단지에 특A급 호재인 것만은 분명하다



블로그 이미지

Link2Me

,
728x90

본 자료는 구글링으로 검색한 내용중에서 필요한 부분을 요약 발췌 정리한 자료다.


북한 경의선 구간 철로 상황은 11년전과 크게 다를바 없다.

북한 철도의 평균 속도가 시속 40 ~ 50km 에 불과하다.

북한 철도의 개보수 비용은 기본 구조물 보수에 전력.통신 등 고려 사항이 많아 가늠하긴 어렵다.

2013년 완공된 라진~하산간 54 km 현대화 사업에는 7천만 달러가 투입돼 km당 약 14억원이 들었다.


시베리아 횡단철도, 중국횡단 철도는 현재 화물운송의 경우 속도가 40~50km를 넘지 않는다.

화물의 경우엔 개보수를 통해 속도를 국제수준에 맞출 수 있을 것으로 보인다.


여객의 경우 평균 시속 100km를 넘기 힘들어, 차라리 고속철 검토가 필요하다는 주장도 제기되고 있다.


교통연구원은 남북 통합 철도망 구축에 최장 30년에 160조 원이 필요하다고 계산했다.

정부는 남북 간 철도 연결 이후 물류비로 연간 북한은 1억 달러, 한국은 8000만 달러의 이익을 얻는 것으로 주장한다. 그러나 정부는 그전에 천문학적인 예산이 투입돼야 한다는 점을 간과하고 있다.


정부는 당장 사업성이 높은 경의선 연결을 우선 추진할 계획이다.

경의선 철도 부설에는 중국도 뛰어들 것으로 보인다.

6월 북·중 정상회담에서 시진핑 중국 국가주석이 김정은 북한 국무위원장에게 신의주-개성 간 철도 및 도로의 개·보수를 제안한 것으로 알려졌다. 중국은 일대일로의 연장선상에서 한반도와의 철도 연계를 추진하고 있다. 한반도 철도를 중국 동북지방의 발전 회랑으로 만들겠다는 것이다.


북한 철도 실태에 관한 자료는 중국과 러시아가 이미 확보한 상태이고 미국과 일본도 북한 진출을 꾀하는 만큼 앞으로 북한 철도 현대화를 누가 주도해 나갈지는 아무도 장담할 수 없는 상황이다.



경의선은 신의주를 통해 유럽까지 이어지는 중국횡단철도(TCR)와 연결되고, 동해선은 나진~하산을 거쳐 시베리아횡단철도(TSR)와 연결된다.



2014년 국토연구원 자료를 보면, 경의선이 중국횡단철도와 연결될 경우 2030년을 기준으로 경의선을 통한 철도 물동량은 3015만t, 동해선이 시베리아횡단철도와 연결될 경우 물동량은 754만t이 될 것이라고 분석했다.


서해안을 산업·물류벨트로 육성하고 동해권은 에너지·자원벨트로 육성하겠다는 문재인 정부의 ‘한반도 신경제지도’ 구상이나, 서남권과 동북권을 양대 축으로 개발하겠다는 북한의 ‘국가경제개발 10개년 전략계획’은 물론, 러시아가 추진 중인 나진-하산 프로젝트, 중국의 동북3성 개발계획, 유엔개발계획(UNDP)의 광역두만강개발계획(GTI) 모두 이런 전망에 기초하고 있다.


문재인 대통령의 남-북-러 협력사업은 크게 세 나라 간 철도 연결, 가스관 연결, 전력망 연결로 구체화된다.

이런 3대 협력사업은 미·북 정상회담으로 북한 핵 문제가 곧 해결될 것이라는 낙관적인 전망이 나오면서 탄력을 받고 있다. 러시아는 가스와 철도를 염두에 두고 있으며 중국은 철도 연결을 이미 상당히 구체적으로 추진하고 있다. 우리 정부도 철도와 가스 연결 사업에 돈 보따리를 풀 기세다. 막대한 국민 혈세가 소요되는 이 거대 프로젝트에 경제성과 리스크, 그리고 기대효과가 어떠한지 따져보는 게 필요하다. 

문 대통령은 러시아 방문 기간에 “철도·전력·가스 등 남-북-러 3각 협력의 주요 사업 구상 가운데 철도연결사업의 추진 가능성이 가장 큰 것으로 보인다”고 말했다. 구체적인 로드맵도 밝혔다. 우선 한·러 간, 남·북 간 공동연구를 각각 병행해 진행하면서 향후 자연스럽게 남-북-러 간 공동연구와 실질협력으로 발전시킨다는 것이다.


현재 독일에서 부산항까지 물건을 수입해 오려면 해상으로 60일 정도가 걸리지만, 철도-해상 복합 운송 시대가 열리면 35일이면 가능할 것이라고 주장한다.


세계 물류는 이미 철도에서 선박으로 넘어간 지 오래다. 2만1000TEU급 선박은 한 번에 무려 2만여 개의 컨테이너를 나를 수 있다. 철도는 보통 60TEU 정도에 불과하다. 앞으로 2만8000TEU급 선박이 보편화하면 선박 운송비는 더 떨어질 것이다. 현재 철도 운송비는 마일당 2.5달러다. 이에 비해 1만 TEU급 선박은 1해리당 0.7달러 수준이다. 한국에서 유럽으로 가는 수출 물량의 경우 철도 수송보다는 해상 수송이 훨씬 저렴하다. 수송 거리가 늘어나고 시간이 더 걸릴지는 몰라도 가격은 ‘넘사벽’이다. 물론 러시아, 중앙아시아 등 유라시아 내륙으로 가는 물류의 경우 철도가 경제성이 있을지 모른다. 그러나 유럽 물량은 해상 운송을 할 수밖에 없다.


문재인 정부는 철도 연결과 함께 남-북-러 가스관 연결도 추진하고 있다.

정부는 남-북-러 가스관 사업을 아직 공식화하지 않았다.
러시아는 세계 2위의 가스 생산국이고 한국은 세계 3위의 가스 수입국이다.
러시아는 극동과 시베리아에서 생산하는 천연가스를 알타이 가스관과 ‘시베리아의 힘’이라는 가스관을 통해 중국에 공급하기로 중국과 계약을 맺었다.
한국-북한-러시아를 통과하는 가스관을 건설하는 사업은 사실 북한 경제에 별 도움이 되지 않는다.

러시아 천연가스의 경쟁 대상은 미국의 셰일가스다. 한국은 미국산 셰일가스로 만든 LNG를 연간 280만t 수입하고 있다. 한국은 최근 미국 셰일가스 LNG의 최대 시장으로 떠오르고 있다. 장차 연간 550만t을 수입할 예정이다.

블로그 이미지

Link2Me

,
728x90

viewport : 뷰포트는 문서의 내용 중 사용자에게 보여주는 영역을 의미
window.inner*은 뷰포트의 크기를 나타내고, screen.*은 스크린의 크기를 나타낸다.

// 가로 길이(너비)
window.innerWidth // 브라우저 창(window) 두께를 제외한 실질적 가로 길이
window.outerWidth // 브라우저 창(window) 두께를 포함한 브라우저 전체 가로 길이


//세로길이(높이)
window.innerHeight // 브라우저 창(window) 두께를 제외한 실질적 세로 길이
window.outerHeight // 브라우저 창(window) 두께를 포함한 브라우저 전체 세로 길이

$(window).width();   // returns width of browser viewport
$(window).height();   // returns height of browser viewport

document.body.scrollWidth // (문서 전체의 너비)
document.body.scrollHeight //(문서 전체의 높이)

$(document).height(); // returns height of HTML document (same as pageHeight in screenshot)
$(document).width(); // returns width of HTML document (same as pageWidth in screenshot)

window.screen.width, window.screen.height
모니터 스크린의 너비와 높이

window.scrollTo(x,y);

<script>
    document.getElementById('scrollBtn').addEventListener('click', function(){
        window.scrollTo(0, 1000);
    })
</script>

블로그 이미지

Link2Me

,