PG備忘録

プログラミングいろいろ

XAMPPでApacheが起動しない件

ポート80は使ってなかったので、なんやろと思ったけど、これで解決した

1.Find out the Apache version you are using, you can find this by looking in Services (Control panel, Admin Tools, Services) and finding Apache in my case it was listed as Apache2.4

2.Close XAMPP.

3.Run cmd as admin.

4.execute 'sc delete "Apache2.4"' (put your version in place of mine and without the surrounding ' ', but with the " " around Apache).

5.execute 'sc delete "mySQL"', again remove the '' when you type it.

6.reopen XAMPP and try starting Apache

stackoverflow.com

Github連携してみた

やりかた

Github for Windowsをダウンロード

desktop.github.com

環境変数のPathにgit.exeへのパスを追加

C:\Users\<自分のユーザー名>\AppData\Local\GitHubDesktop\app-0.6.2\resources\app\git\cmd

Android StudioでShare Project on Github を選択

Repository Nameにアプリの名前をいれる(Remote Nameはoriginのままでおk)

タスク管理アプリ ver3

一応これが最終バージョン

必要なファイル

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="jp.gr.java_conf.oleeapps.mytask3">
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-sdk
        android:minSdkVersion="15" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/checklist_icon"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.AppCompat.DayNight.DarkActionBar">
        <activity android:name=".MainActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".AddActivity"
            android:label="@string/add_name">
        </activity>
        <activity android:name=".UpdateActivity"
            android:label="@string/edit_name">
        </activity>

    </application>
</manifest>

MyDBHelper.java

package jp.gr.java_conf.oleeapps.mytask3;

        import android.content.Context;
        import android.database.sqlite.SQLiteDatabase;
        import android.database.sqlite.SQLiteOpenHelper;

/**
 * Created by orisa on 2017/06/08.
 */

public class MyDBHelper extends SQLiteOpenHelper {

    public MyDBHelper(Context context){
        super(context, "TASK_DB", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        //SQL文を入れる
        String sql = "CREATE TABLE default_tb(_id INTEGER PRIMARY KEY NOT NULL, " +
                "task_col TEXT, date_col TEXT, time_col TEXT, checked_col INTEGER);";
        db.execSQL(sql);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginEnd="20dp"
    android:layout_marginStart="20dp"
    android:layout_marginTop="10dp"
    tools:context="jp.gr.java_conf.oleeapps.mytask3.MainActivity">

    <LinearLayout
        android:id="@+id/layout_top"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:gravity="center_horizontal"
        android:orientation="horizontal">

        <ImageButton
            android:id="@+id/prevBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginEnd="20dp"
            android:layout_marginRight="20dp"
            android:layout_toStartOf="@+id/showDate"
            android:layout_toLeftOf="@+id/showDate"
            android:layout_weight="1"
            android:background="@null"
            app:srcCompat="@drawable/ic_left_arrow" />

        <TextView
            android:id="@+id/showDate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="false"
            android:layout_centerHorizontal="true"
            android:layout_gravity="center"
            android:fontFamily="sans-serif-smallcaps"
            android:textAppearance="@style/TextAppearance.AppCompat.Large"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.502"
            tools:layout_editor_absoluteX="157dp"
            tools:layout_editor_absoluteY="248dp" />

        <ImageButton
            android:id="@+id/nextBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/showDate"
            android:layout_gravity="center"
            android:layout_marginStart="20dp"
            android:layout_marginLeft="20dp"
            android:layout_toEndOf="@+id/showDate"
            android:layout_toRightOf="@+id/showDate"
            android:background="@null"
            app:srcCompat="@drawable/ic_right_arrow" />
    </LinearLayout>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/layout_top"
        android:layout_marginTop="10dp"
        android:orientation="vertical">

        <TextView
            android:id="@+id/textView4"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#009688"
            android:fontFamily="sans-serif-smallcaps"
            android:paddingLeft="5dp"
            android:paddingStart="5dp"
            android:text="AM"
            android:textAppearance="@style/TextAppearance.AppCompat.Medium"
            android:textColor="#FFFFFF" />

        <ScrollView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginTop="5dp"
            android:layout_weight="1"
            android:fillViewport="true">

            <LinearLayout
                android:id="@+id/amLayout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"></LinearLayout>
        </ScrollView>

        <TextView
            android:id="@+id/textView5"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:background="#009688"
            android:fontFamily="sans-serif-smallcaps"
            android:paddingLeft="5dp"
            android:paddingStart="5dp"
            android:text="PM"
            android:textAppearance="@style/TextAppearance.AppCompat.Medium"
            android:textColor="#FFFFFF" />

        <ScrollView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginTop="5dp"
            android:layout_weight="1"
            android:fillViewport="true">

            <LinearLayout
                android:id="@+id/pmLayout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">

            </LinearLayout>
        </ScrollView>

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentStart="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:layout_gravity="end"
            android:layout_marginBottom="16dp"
            android:layout_marginEnd="16dp"
            android:layout_marginRight="16dp"
            android:clickable="true"
            app:fabSize="normal"
            app:srcCompat="@drawable/ic_add" />

    </LinearLayout>

</RelativeLayout>

MainActivity.java

package jp.gr.java_conf.oleeapps.mytask3;

import android.app.DatePickerDialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import java.util.Calendar;

import android.os.Build;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.DatePicker;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    //部品の変数
    TextView showDate;
    ImageButton prevBtn, nextBtn;
    LinearLayout amLayout, pmLayout;
    FloatingActionButton fab;

    //日付を格納する変数
    String today_str;
    Calendar today_cal;

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

        //部品の取得
        showDate = (TextView)findViewById(R.id.showDate);
        prevBtn = (ImageButton) findViewById(R.id.prevBtn);
        nextBtn = (ImageButton) findViewById(R.id.nextBtn);
        amLayout = (LinearLayout)findViewById(R.id.amLayout);
        pmLayout = (LinearLayout)findViewById(R.id.pmLayout);
        fab = (FloatingActionButton)findViewById(R.id.fab);

        //日付表示欄にリスナーを登録
        showDate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Calendarインスタンスの取得
                Calendar cal = Calendar.getInstance();
                //DatePickerDialogインスタンスの生成
                DatePickerDialog dialog = new DatePickerDialog(MainActivity.this,
                        new DatePickerDialog.OnDateSetListener() {
                            @Override
                            public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
                                //日付を取得
                                today_str = String.format("%d/%02d/%02d", year, month+1, dayOfMonth);
                                today_cal.set(year, month, dayOfMonth);
                                //日付を表示
                                showDate.setText(today_str+" "+calToDay(today_cal));
                                //データベースを表示
                                showDB();
                            }
                        }, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH));
                //DatePickerDialogの表示
                dialog.show();
            }
        });

        //矢印ボタンにリスナーを設定
        prevBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Calendar変数を前日に設定する
                today_cal.add(Calendar.DAY_OF_MONTH, -1);
                today_str = calToStr(today_cal);
                //日付を表示
                showDate.setText(today_str+" "+calToDay(today_cal));
                //データベースを表示
                showDB();
            }
        });

        nextBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Calendar変数を翌日に設定する
                today_cal.add(Calendar.DAY_OF_MONTH, 1);
                today_str = calToStr(today_cal);
                //日付を表示
                showDate.setText(today_str+" "+calToDay(today_cal));
                //データベースを表示
                showDB();
            }
        });

        //FloatingActionButtonにリスナーを登録
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Intentインスタンスの生成
                Intent intent = new Intent(getApplication(), AddActivity.class);
                //activityの開始
                startActivity(intent);
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();

        //今日の日付を取得
        today_cal = Calendar.getInstance();
        today_str = calToStr(today_cal);
        //日付を表示
        showDate.setText(today_str+" "+calToDay(today_cal));

        //データベースを表示
        showDB();
    }


    //Action Bar関連
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_activity_actions, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);

        //dialogの設定
        builder.setMessage("Delete all tasks?");

        //OKボタンの設定
        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                //データベースの全削除
                deleteAllDB();
                //データベースの表示
                showDB();
            }
        });

        //CANCELボタンの設定
        builder.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
            }
        });

        switch (item.getItemId()){
            case R.id.deleteAll:
                //dialogの描画
                builder.create();
                builder.show();
                break;
            default:
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    //CalendarからStringに変換するメソッド
    protected String calToStr(Calendar cal){
        String str = String.format("%d/%02d/%02d", cal.get(Calendar.YEAR),
                cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH));
        return str;
    }

    //データベースを表示するメソッド
    protected void showDB(){
        //データベースの取得
        MyDBHelper helper = new MyDBHelper(MainActivity.this);
        final SQLiteDatabase db = helper.getWritableDatabase();

        //表示のクリア
        amLayout.removeAllViews();
        pmLayout.removeAllViews();

        //検索して表示
        final Cursor c_am = db.query("default_tb", new String[]{"task_col", "checked_col"},
                "date_col =? AND time_col =?", new String[] {today_str, "AM"},
                null, null, null);
        boolean bool = c_am.moveToFirst();
        while(bool){
            //CheckBoxの設定
            final CheckBox cb = new CheckBox(MainActivity.this);
            cb.setText(c_am.getString(0));
            if(Build.VERSION.SDK_INT < 23){
                cb.setTextAppearance(MainActivity.this, R.style.TextAppearance_AppCompat_Small);
            }else{
                cb.setTextAppearance(R.style.TextAppearance_AppCompat_Small);
            }

            //CheckBoxにリスナーをつける
            cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    //DBのアップデート処理
                    ContentValues val = new ContentValues();
                    val.put("checked_col", 1);
                    db.update("default_tb", val, "task_col =?", new String[]{cb.getText().toString()});
                }
            });
            //checkedが1(=TRUE)なら、checkedにする
            if(c_am.getInt(1) == 1){
                cb.setChecked(true);
            }

            //全体のlayoutに追加
            amLayout.addView(setRow(cb));
            bool = c_am.moveToNext();
        }
        c_am.close();

        final Cursor c_pm = db.query("default_tb", new String[]{"task_col", "checked_col"},
                "date_col =? AND time_col =?", new String[] {today_str, "PM"},
                null, null, null);
        bool = c_pm.moveToFirst();
        while(bool){
            //CheckBoxの設定
            final CheckBox cb = new CheckBox(MainActivity.this);
            cb.setText(c_pm.getString(0));
            if(Build.VERSION.SDK_INT < 23){
                cb.setTextAppearance(MainActivity.this, R.style.TextAppearance_AppCompat_Small);
            }else{
                cb.setTextAppearance(R.style.TextAppearance_AppCompat_Small);
            }
            //CheckBoxにリスナーをつける
            cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    //DBのアップデート処理
                    ContentValues val = new ContentValues();
                    val.put("checked_col", 1);
                    db.update("default_tb", val, "task_col =?", new String[]{cb.getText().toString()});
                }
            });
            //checkedが1(=TRUE)なら、checkedにする
            if(c_pm.getInt(1) == 1){
                cb.setChecked(true);
            }

            //全体のlayoutに追加
            pmLayout.addView(setRow(cb));
            bool = c_pm.moveToNext();
        }
        c_pm.close();
    }

    //showDBの中で、部品を配置するメソッド
    protected LinearLayout setRow(CheckBox cb_param){
        //rowの高さ
        int row_h = dpToPx(this, 25);
        int mar_l = dpToPx(this, 13);
        int mar_t = dpToPx(this, 7);

        //CheckBox変数
        final CheckBox cb = cb_param;
        LinearLayout.LayoutParams cb_lp = new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT, row_h);
        cb.setLayoutParams(cb_lp);

        //ボタンのLayoutParamsの設定
        LinearLayout.LayoutParams btn_params = new LinearLayout.LayoutParams(
                row_h, row_h);
        btn_params.setMargins(mar_l, 0, 0, 0);

        //アイコンの設定
        ImageButton edit_btn = new ImageButton(MainActivity.this);
        edit_btn.setImageResource(R.drawable.ic_edit);
        if(Build.VERSION.SDK_INT >= 16){
            edit_btn.setBackground(null);
        } else {
            edit_btn.setBackgroundDrawable(null);
        }
        edit_btn.setLayoutParams(btn_params);
        edit_btn.setScaleType(ImageButton.ScaleType.CENTER_CROP);
        edit_btn.setPadding(0, 0, 0, 0);

        ImageButton delete_btn = new ImageButton(MainActivity.this);
        delete_btn.setImageResource(R.drawable.ic_delete);
        if(Build.VERSION.SDK_INT >= 16){
            delete_btn.setBackground(null);
        } else {
            delete_btn.setBackgroundDrawable(null);
        }
        delete_btn.setLayoutParams(btn_params);
        delete_btn.setScaleType(ImageButton.ScaleType.CENTER_CROP);
        delete_btn.setPadding(0, 0, 0, 0);

        //リスナーの登録
        edit_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //UPDATE画面に遷移
                Intent intent = new Intent(getApplication(), UpdateActivity.class);
                //intentにデータを渡す
                intent.putExtra("task_data", cb.getText().toString());
                startActivity(intent);
            }
        });
        delete_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //データベースを削除
                deleteDb(cb.getText().toString());

                //CheckBoxが入っているLayoutを取得
                LinearLayout ll = (LinearLayout)cb.getParent();
                //Layoutが入ってるLayoutを取得
                LinearLayout ll_p = (LinearLayout)ll.getParent();
                //CheckBoxの入っているLayoutのindexを取得
                int ll_index = ((ViewGroup)ll_p).indexOfChild(ll);
                //CheckBoxの入っているLayoutを削除
                ll_p.removeViewAt(ll_index);
            }
        });

        //LinearLayoutの設定
        LinearLayout layout = new LinearLayout(MainActivity.this);//インスタンスの生成
        layout.setGravity(Gravity.CENTER_VERTICAL);//Gravityの設定

        //CheckBoxとImageButtonの間をうめるやつ
        View view = new View(MainActivity.this);
        LinearLayout.LayoutParams v_lp = new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT, 1, 1f);
        view.setLayoutParams(v_lp);

        //LinearLayoutに部品を追加
        layout.addView(cb);
        layout.addView(view);
        layout.addView(edit_btn);
        layout.addView(delete_btn);

        //layoutのLayoutParams
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        params.setMargins(0, mar_t, 0, 0);
        layout.setLayoutParams(params);

        return layout;
    }

    //データベースを削除
    protected void deleteDb(String task_str){
        //データベースの取得
        MyDBHelper helper = new MyDBHelper(MainActivity.this);
        SQLiteDatabase db = helper.getWritableDatabase();

        //データベースの削除
        db.delete("default_tb", "task_col =?", new String[]{task_str});
    }

    //データベースの全削除をするメソッド
    protected void deleteAllDB(){
        //データベースの取得
        MyDBHelper helper = new MyDBHelper(MainActivity.this);
        SQLiteDatabase db = helper.getWritableDatabase();

        //データベース削除
        db.delete("default_tb", null, null);
    }

    protected String calToDay(Calendar cal){
        int day_int = cal.get(Calendar.DAY_OF_WEEK);
        switch (day_int){
            case 1:
                return getString(R.string.sun);
            case 2:
                return getString(R.string.mon);
            case 3:
                return getString(R.string.tue);
            case 4:
                return getString(R.string.wed);
            case 5:
                return getString(R.string.thu);
            case 6:
                return getString(R.string.fri);
            case 7:
                return getString(R.string.sat);
            default:
                return getString(R.string.error);
        }
    }

    protected int dpToPx(Context context, int dp){
        float d = context.getResources().getDisplayMetrics().density;
        return (int)((dp*d)+0.5);
    }
}

activity_add.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:fontFamily="sans-serif-smallcaps"
        android:text="@string/task_msg"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium" />

    <EditText
        android:id="@+id/updTask"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/textView"
        android:layout_marginTop="10dp"
        android:ems="10"
        android:inputType="text" />

    <TextView
        android:id="@+id/textView6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/updTask"
        android:layout_marginTop="30dp"
        android:fontFamily="sans-serif-smallcaps"
        android:text="@string/date_msg"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium" />

    <EditText
        android:id="@+id/updDate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/textView6"
        android:layout_marginTop="10dp"
        android:ems="10"
        android:focusable="false"
        android:inputType="date" />

    <TextView
        android:id="@+id/textView7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/updDate"
        android:layout_marginTop="30dp"
        android:fontFamily="sans-serif-smallcaps"
        android:text="@string/time_msg"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium" />

    <Spinner
        android:id="@+id/spinner"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/textView7"
        android:layout_marginTop="10dp"
        android:spinnerMode="dialog" />

    <Button
        android:id="@+id/okBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_marginStart="30dp"
        android:fontFamily="sans-serif-smallcaps"
        android:text="@string/ok" />

    <Button
        android:id="@+id/cancelBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_marginEnd="30dp"
        android:layout_marginRight="30dp"
        android:fontFamily="sans-serif-smallcaps"
        android:text="@string/cancel" />

</RelativeLayout>

AddActivity.java

package jp.gr.java_conf.oleeapps.mytask3;

import android.app.DatePickerDialog;
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import java.util.Calendar;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.Toast;

/**
 * Created by orisa on 2017/06/08.
 */

public class AddActivity extends AppCompatActivity {

    //部品の取得
    EditText addTask, addDate;
    Spinner spinner;
    Button okBtn, cancelBtn;

    //Spinner用の変数
    String[] items = {"AM", "PM"};

    //データを入れる用の変数
    String task, date, time;

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

        //部品の取得
        addTask = (EditText)findViewById(R.id.updTask);
        addDate = (EditText)findViewById(R.id.updDate);
        spinner = (Spinner)findViewById(R.id.spinner);
        okBtn = (Button)findViewById(R.id.okBtn);
        cancelBtn = (Button)findViewById(R.id.cancelBtn);

        //日付の入力の設定
        addDate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Calendarインスタンスの生成
                Calendar cal = Calendar.getInstance();
                //DatePickerDialogインスタンスの生成
                DatePickerDialog dialog = new DatePickerDialog(AddActivity.this,
                        new DatePickerDialog.OnDateSetListener() {
                            @Override
                            public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
                                //日付を取得して表示
                                addDate.setText(String.format("%d/%02d/%02d", year, month+1, dayOfMonth));
                            }
                        }, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH),cal.get(Calendar.DAY_OF_MONTH));
                //DatePickerDialogの表示
                dialog.show();
            }
        });

        //AM/PM入力の設定
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(AddActivity.this, android.R.layout.simple_spinner_dropdown_item,
                items);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(adapter);

        //Spinnerにリスナーを登録
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                //選択されたStringを取得
                time = (String)parent.getSelectedItem();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

        //データベースの作成
        MyDBHelper helper = new MyDBHelper(AddActivity.this);
        final SQLiteDatabase db = helper.getWritableDatabase();

        //OKボタンクリック時の処理
        okBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //taskとdateを取得
                task = addTask.getText().toString();
                date = addDate.getText().toString();
                //ContentValuesにデータを入れる
                ContentValues val = new ContentValues();
                val.put("task_col", task);
                val.put("date_col", date);
                val.put("time_col", time);
                val.put("checked_col", 0);
                //データベースに登録
               db.insert("default_tb", null, val);
                //activityの終了
                finish();
            }
        });

        //CANCELボタンクリック時の処理
        cancelBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //activityの終了
                finish();
            }
        });

    }
}

activity_update.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:fontFamily="sans-serif-smallcaps"
        android:text="@string/task_msg"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium" />

    <EditText
        android:id="@+id/updTask"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/textView"
        android:layout_marginTop="10dp"
        android:ems="10"
        android:inputType="text" />

    <TextView
        android:id="@+id/textView6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/updTask"
        android:layout_marginTop="30dp"
        android:fontFamily="sans-serif-smallcaps"
        android:text="@string/date_msg"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium" />

    <EditText
        android:id="@+id/updDate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/textView6"
        android:layout_marginTop="10dp"
        android:ems="10"
        android:focusable="false"
        android:inputType="date" />

    <TextView
        android:id="@+id/textView7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/updDate"
        android:layout_marginTop="30dp"
        android:fontFamily="sans-serif-smallcaps"
        android:text="@string/time_msg"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium" />

    <Spinner
        android:id="@+id/spinner"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/textView7"
        android:layout_marginTop="10dp"
        android:spinnerMode="dialog" />

    <Button
        android:id="@+id/updBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginLeft="30dp"
        android:layout_marginStart="30dp"
        android:fontFamily="sans-serif-smallcaps"
        android:text="@string/edit" />

    <Button
        android:id="@+id/cancelBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_marginEnd="30dp"
        android:layout_marginRight="30dp"
        android:fontFamily="sans-serif-smallcaps"
        android:text="@string/cancel" />

</RelativeLayout>

UpdateActivity.java

package jp.gr.java_conf.oleeapps.mytask3;

import android.app.DatePickerDialog;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import java.util.Calendar;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;

/**
 * Created by orisa on 2017/06/16.
 */

public class UpdateActivity extends AppCompatActivity {

    //部品の変数
    EditText updTask, updDate;
    Spinner spinner;
    Button updBtn, cancelBtn;

    //Spinner用の変数
    String[] items = {"AM", "PM"};

    //データを入れる用の変数
    String task, date, time;

    //intentからデータを受け取る用の変数
    String task_init;

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

        //部品の取得
        updTask = (EditText)findViewById(R.id.updTask);
        updDate = (EditText)findViewById(R.id.updDate);
        spinner = (Spinner)findViewById(R.id.spinner);
        updBtn = (Button) findViewById(R.id.updBtn);
        cancelBtn = (Button)findViewById(R.id.cancelBtn);

        //日付入力の設定
        updDate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Calendarインスタンスの生成
                Calendar cal = Calendar.getInstance();
                //DatePickerDialogの設定
                DatePickerDialog dialog = new DatePickerDialog(UpdateActivity.this,
                        new DatePickerDialog.OnDateSetListener() {
                            @Override
                            public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
                                //日付を表示
                                updDate.setText(String.format("%d/%02d/%02d", year, month+1, dayOfMonth));
                            }
                        }, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH));
                //DatePickerDialogの表示
                dialog.show();
            }
        });

        //AM/PM入力の設定
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(UpdateActivity.this,
                android.R.layout.simple_spinner_dropdown_item, items);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(adapter);

        //Spinnerにリスナーを設定
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                //データを格納
                time = (String)parent.getSelectedItem();
            }
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

        //UPDATEボタンにリスナーを設定
        updBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //データの取得
                task = updTask.getText().toString();
                date = updDate.getText().toString();
                //データベースの更新
                MyDBHelper helper = new MyDBHelper(UpdateActivity.this);
                SQLiteDatabase db = helper.getWritableDatabase();
                ContentValues val = new ContentValues();
                val.put("task_col", task);
                val.put("date_col", date);
                val.put("time_col", time);
                db.update("default_tb", val, "task_col =?", new String[] {task_init});
                finish();
            }
        });

        //CANCELボタンにリスナーを設定
        cancelBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //activityの終了
                finish();
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();

        // intentのデータを受け取る
        Intent intent = getIntent();
        task_init = intent.getStringExtra("task_data");

        //データベースを検索
        MyDBHelper helper = new MyDBHelper(UpdateActivity.this);
        SQLiteDatabase db = helper.getWritableDatabase();

        Cursor c = db.query("default_tb", new String[]{"date_col", "time_col"},
                "task_col =?", new String[]{task_init}, null, null, null);
        boolean bool = c.moveToFirst();
        while (bool){
            //dateとtimeを取得
            date = c.getString(0);
            time = c.getString(1);
            //Cursorを次に移動
            bool = c.moveToNext();
        }
        //Cursorをclose
        c.close();

        //データを表示
        updTask.setText(task_init);
        updDate.setText(date);
        int pos;
        if(time.equals("AM")){
            pos = 0;
        }
        else {
            pos = 1;
        }
        spinner.setSelection(pos);
    }
}

アプリ公開しました

Google Play Storeでアプリ公開しました
play.google.com

予想外にめんどくさかったので、以下自分用メモ

最低限用意するもの

release apk

qiita.com

画像

画像タイプ サイズ ファイル形式 備考
スクリーンショット min:320px, max:3840px JPG / 24bit PNG 最低2枚必要
高解像度アイコン 512x512 32bit PNG -
ヘッダー画像 1024x500 JPG / 24bit PNG -

文章

  • アプリ名(MAX 50文字)
  • 簡単な説明(MAX 80文字)
  • 詳しい説明(MAX 4000文字)

アプリを公開する時の注意

package名

com.example... だとダメなので、そうなってたら変更する
okuzawats.com

パッケージ名の取得は以下のサイトがおすすめ
Package Registration Page

SEO対策

工夫しないと、アプリのキーワードを入れてもヒットしないので適宜対策しようね!
www.find-job.net

Creative Commonsとかのライセンス表記

以下を参考に
Best practices for attribution - Creative Commons

Calendar↔Stringを相互に変換

SQLiteDatabaseでは日付に関するオブジェクトはそのまま格納できない
→ TEXT = String型で格納する
→ どうやって変換するの?
というのが、下記のコード

ポイント

  • SimpleDateFormatを使って変換する
  • ミリ秒までformatしないと、情報が失われるので注意
  • Calendar.MONTHは0-11だけど、そこらへんは考えなくてok
package com.example.orisa.mycal1;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    //部品の変数
    TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //部品の取得
        tv = (TextView)findViewById(R.id.tv);

        Calendar cal1 = Calendar.getInstance();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS");
        String str1 = sdf.format(cal1.getTime());

        Calendar cal2 = Calendar.getInstance();

        try{
            cal2.setTime(sdf.parse(str1));
            
            if(cal1.equals(cal2)){
                tv.setText("true");
            } else {
                tv.setText("false");
            }

        }catch (ParseException e){
            tv.setText("exception");
        }
    }
}

ImageButtonで画像を縮小する方法

ImageButtonのサイズを小さくしたとき、その中に画像をおさめる方法

概要

  1. LayoutParamsでheight・widthを指定
  2. ボタンにLayoutParamsを設定
  3. ボタンのScaleTypeをCENTER_CROPに指定

コード

//ボタンのLayoutParamsの設定
LinearLayout.LayoutParams btn_params = new LinearLayout.LayoutParams(80, 80);

//アイコンの設定
ImageButton btn = new ImageButton(MainActivity.this);
btn.setImageResource(R.drawable.ic_edit);
edit_btn.setLayoutParams(btn_params);
edit_btn.setScaleType(ImageButton.ScaleType.CENTER_CROP);

長押しでメニュー表示+フォントのカスタマイズ

初期画面
f:id:olee46:20170621034951j:plain:h300

メニュー表示画面
f:id:olee46:20170621034955j:plain:h300

機能

  • TextViewの表示
  • TextView長押し → メニュー表示

ポイント

長押しでメニュー表示する

  • registerForContextMenu(View view)
  • onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
  • onContextItemSelected(MenuItem item)

の3つのメソッドを使う(詳細はコード参照)
techbooster.org

フォントのカスタマイズ

f:id:olee46:20170621034958j:plain:h300
Projectビューにする → app > mainの下にassetsフォルダを作る → ttfファイルを追加

背景色を動的に指定

tv.setBackgroundColor(Color.parseColor("#FFD740"));

www.javadrive.jp

必要なファイル

activity_main.xml

f:id:olee46:20170621035001j:plain:h300

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.orisa.mymenu1.MainActivity">

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:layout_margin="10dp"
        android:elevation="3dp"
        android:fontFamily="casual"
        android:padding="10dp"
        android:text="資料を作る"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</RelativeLayout>

MainActivity.java

package com.example.orisa.mymenu1;

import android.graphics.Color;
import android.graphics.Typeface;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    //ContextMenu用の定数
    static final int MENU_ID_EDIT = 0;
    static final int MENU_ID_DELETE = 1;

    TextView tv;

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

        tv = (TextView)findViewById(R.id.tv);
        //背景色を指定
        tv.setBackgroundColor(Color.parseColor("#FFD740"));

        registerForContextMenu(tv);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);

        //Menuに項目を追加する
        menu.add(0, MENU_ID_EDIT, 0, "edit");
        menu.add(0, MENU_ID_DELETE, 0, "delete");
    }

    //Menuの項目をクリックしたときの動作
    @Override
    public boolean onContextItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case MENU_ID_EDIT:
                Toast.makeText(MainActivity.this, "edit", Toast.LENGTH_SHORT).show();
                return true;
            case MENU_ID_DELETE:
                Toast.makeText(MainActivity.this, "delete", Toast.LENGTH_SHORT).show();
                return true;
            default:
                return super.onContextItemSelected(item);
        }
    }
}