sqliteの設定

ContractとOpenHelperのクラスを作成します。OepnHelperはSQLiteOpenHelperを継承します。
New->Other->ContentProviderから新規にcomponentを作成し、呼び出します。authorityは、packageとContentProvider名です。(self.mymemoapp.MemeoContentProvider)

package self.mymemoapp;

import android.provider.BaseColumns;


public final class MemoContract {

    public MemoContract(){}

    public static abstract class Memos implements BaseColumns {
        public static final String TABLE_NAME = "memos";
        public static final String COL_TITLE = "title";
        public static final String COL_BODY = "body";
        public static final String COL_CREATE = "created";
        public static final String TABLE_UPDATE = "updated";
    }
}
package self.mymemoapp;

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

public class MemoOpenHelper extends SQLiteOpenHelper {
    public static final String DB_NAME = "myapp.db";
    public static final int DB_VERSION = 1;

    public static final String CREATE_TABLE =
            "create table memos (" +
                "_id integer primary key autoincrement, "+
            "title text, " +
            "body text, " +
            "created datetime default current_timestamp, " +
            "updated datetime default current_timestamp)";

    public static final String INIT_TABLE =
            "insert into memos (title, body) values " +
                    "('t1', 'b1'), " +
                    "('t2', 'b2'), " +
                    "('t3', 'b3'), ";

    public static final String DROP_TABLE =
            "drop table if exists " + MemoContract.Memos.TABLE_NAME;

    public MemoOpenHelper(Context c){
        super(c, DB_NAME, null, DB_VERSION);
    }
    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        db.execSQL(CREATE_TABLE);
        db.execSQL(INIT_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        db.execSQL(DROP_TABLE);
        onCreate(db);
    }
}

SQLiteとAndroid

UserOpenHelperでSQLiteOpenHelperを継承します。

package self.mydbapp;

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

/**
 * Created by narishige on 2016/11/21.
 */

public class UserOpenHelper extends SQLiteOpenHelper {

    public static final String DB_NAME = "myapp.db";
    public static final int DB_VERSION = 1;
    public static final String CREATE_TABLE =
            "create table " + UserContract.Users.TABLE_NAME + " (" +
                    UserContract.Users._ID + " integer primary key autoincrement," +
                    UserContract.Users.COL_NAME + "name text," +
                    UserContract.Users.COL_SCORE + "score integer)";
    public static final String INIT_TABLE =
            "insert into users (name, score) values " +
                    "('yoshimoto', 55), " +
                    "('kimura', 45), " +
                    "('igarashi', 82)";
    public static final String DROP_TABLE =
            "drop table if exists users";

    public UserOpenHelper(Context c){
        super(c, DB_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        // create table
        sqLiteDatabase.execSQL(CREATE_TABLE);
        // init table
        sqLiteDatabase.execSQL(INIT_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        // drop table
        sqLiteDatabase.execSQL(DROP_TABLE);
        // onCreate
        onCreate(sqLiteDatabase);
    }
}

insert, delete, update

        UserOpenHelper userOpenHelper = new UserOpenHelper(this);
        SQLiteDatabase db = userOpenHelper.getWritableDatabase();
        // open db
        ContentValues newUser = new ContentValues();
        newUser.put(UserContract.Users.COL_NAME, "tanaka");
        newUser.put(UserContract.Users.COL_SCORE, "42");
        long newID = db.insert(
          UserContract.Users.TABLE_NAME,
                null,
                newUser
        );
        
        ContentValues newScore = new ContentValues();
        newScore.put(UserContract.Users.COL_SCORE, 100);
        int updatedCount = db.update(
                UserContract.Users.TABLE_NAME,
                newScore,
                UserContract.Users.COL_NAME + " = ?",
                new String[] {"sakai"}
        );
        int deletedCount = db.delete(
          UserContract.Users.TABLE_NAME,
                UserContract.Users.COL_NAME + " = ?",
                new String[] {"sakai"}
        );
        
        Cursor c = null;
        c = db.query(
                UserContract.Users.TABLE_NAME,
                null, // fields
                null, // where
                null, // where arg
                null, // groupby
                null,
                null
        );

トランザクション

 try {
            db.beginTransaction();
            db.execSQL("update users " +
                    "set score = score + 10 " +
                    "where name = 'kaneko'");
            db.execSQL("update users " +
                    "set score = score + 10 " +
                    "where name = 'muraoka'");
        } catch(SQLException e){
            e.printStackTrace();
        } finally {
            db.endTransaction();
        }

ブラウザ

%e7%84%a1%e9%a1%8c

package self.mybrowser;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Patterns;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.EditText;

public class MainActivity extends AppCompatActivity {

    private WebView myWebView;
    private EditText urlText;

    private static final String INITIAL_WEBSITE = "http://finance.yahoo.co.jp";



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

        myWebView = (WebView) findViewById(R.id.myWebView);
        urlText = (EditText) findViewById(R.id.urlText);

        myWebView.getSettings().setJavaScriptEnabled(true);
        myWebView.setWebViewClient(new WebViewClient(){
            @Override
                    public void onPageFinished(WebView view, String url){
                getSupportActionBar().setSubtitle(view.getTitle());
                urlText.setText(url);
            }
        });
        myWebView.loadUrl(INITIAL_WEBSITE);
    }

    public void clearUrl(View view){
        urlText.setText("");
    }

    public void showWebSite(View view){
        String url = urlText.getText().toString().trim();

        if (!Patterns.WEB_URL.matcher(url).matches()){
            urlText.setError("Invalid URL");
        } else {
            if(url.startsWith("http;//") && !url.startsWith("https://")){
                url = "http://" + url;
            }
            myWebView.loadUrl(url);
        }
    }

    @Override
    public void onBackPressed(){
        if (myWebView.canGoBack()){
            myWebView.goBack();
            return;
        }
        super.onBackPressed();
    }

    @Override
    protected void onDestroy(){
        super.onDestroy();
        if(myWebView != null){
            myWebView.stopLoading();
            myWebView.setWebViewClient(null);
            myWebView.destroy();
        }
        myWebView = null;
    }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="self.mybrowserapp.MainActivity">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:layout_weight="1"
            android:id="@+id/urlText"
            android:layout_width="0dp"
            android:onClick="clearUrl"
            android:inputType="text|textNoSuggestions"
            android:layout_height="wrap_content"/>

        <Button
            android:text="Browse"
            android:onClick="showWebsite"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <WebView
        android:layout_weight="1"
        android:id="@+id/myWebView"
        android:layout_width="match_parent"
        android:layout_height="0dp"></WebView>

</LinearLayout>

SystemClockによるタイムウォッチ

SystemClock.elapsedRealtimeからstartTimeを引いた時間を表示しています。
参考:https://developer.android.com/reference/android/os/SystemClock.html

リフェレンス
handler:A Handler allows you to send and process Message and Runnable objects associated with a thread’s MessageQueue. Each Handler instance is associated with a single thread and that thread’s message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it — from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
SimpleDateFormat:is a concrete class for formatting and parsing dates in a locale-sensitive manner. It allows for formatting (date -> text), parsing (text -> date), and normalization.

package self.stopwatchapp;

import android.icu.text.SimpleDateFormat;
import android.os.Handler;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.util.Locale;

public class MainActivity extends AppCompatActivity {

    private long startTime;
    private long elapsedTime = 0l;

    private Handler handler = new Handler();
    private Runnable updateTimer;

    private Button startButton;
    private Button stopButton;
    private Button resetButton;
    private TextView timerLabel;

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


        startButton = (Button) findViewById(R.id.startButton);
        stopButton = (Button) findViewById(R.id.stopButton);
        resetButton = (Button) findViewById(R.id.resetButton);
        timerLabel = (TextView) findViewById(R.id.timerLabel);

        setButtonState(true, false, false);


    }

    public void setButtonState(boolean start, boolean stop, boolean reset){
        startButton.setEnabled(start);
        stopButton.setEnabled(stop);
        resetButton.setEnabled(reset);
    }

    public void startTimer(View view){
        // starttime
        startTime = SystemClock.elapsedRealtime(); //起動からの経過時間

        // 現在の経過時間
        // Handler -> Runnable -> UI
        updateTimer = new Runnable(){
            @Override
            public void run() {
                long t = SystemClock.elapsedRealtime() - startTime + elapsedTime;
                SimpleDateFormat sdf = new SimpleDateFormat("mm:ss.SSS", Locale.US);
                timerLabel.setText(sdf.format(t));
                handler.removeCallbacks(updateTimer);
                handler.postDelayed(updateTimer, 10);
            }
        };
        handler.postDelayed(updateTimer, 10);

        // button
        setButtonState(false, true, false);
    }
    public void stopTimer(View view){
        elapsedTime += SystemClock.elapsedRealtime() - startTime;
        handler.removeCallbacks(updateTimer);
        setButtonState(true, false, true);
    }
    public void resetTimer(View view) {
        elapsedTime = 0l;
        timerLabel.setText("00:00:000");
        setButtonState(true, false, false);
    }

}

LinearLayoutのverticalとhorizontal

LinearLayoutのvertical中に、LinearLayoutのhorizontalで、tableのようなレイアウトを実現しています。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="self.stopwatchapp.MainActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_weight="1"
        android:layout_height="0dp"
        android:gravity="center"
        android:textSize="64sp"
        android:textStyle="bold"
        android:id="@+id/timerLabel"
        android:text="00:00.000" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_weight="1"
        android:orientation="horizontal"
        android:layout_height="0dp">

    <Button
        android:layout_width="0dp"
        android:layout_weight="1"
        android:text="Start"
        android:id="@+id/startButton"
        android:onClick="startTimer"
        android:layout_height="wrap_content"
        />

        <Button
            android:layout_width="0dp"
            android:layout_weight="1"
            android:text="Stop"
            android:id="@+id/stopButton"
            android:onClick="stopTimer"
            android:layout_height="wrap_content"
            />

        <Button
            android:layout_width="0dp"
            android:layout_weight="1"
            android:text="Reset"
            android:id="@+id/resetButton"
            android:onClick="resetTimer"
            android:layout_height="wrap_content"
            />

    </LinearLayout>
</LinearLayout>

classはbooleanで判定しています。

        startButton = (Button) findViewById(R.id.startButton);
        stopButton = (Button) findViewById(R.id.stopButton);
        resetButton = (Button) findViewById(R.id.resetButton);

        setButtonState(true, false, false);


    }

    public void setButtonState(boolean start, boolean stop, boolean reset){
        startButton.setEnabled(start);
        stopButton.setEnabled(stop);
        resetButton.setEnabled(reset);
    }

AndroidManifest.xml

AndroidManifest.xmlのandroid:parentActivityNameで、Activityを元画面に戻します。

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

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".MyResult"
            android:parentActivityName="self.namescoreapp.MyForm"></activity>
    </application>

また、strings.xmlにtextを記載し、activityのxmlからは@string/で呼び出しています。

<EditText
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:id="@+id/myEditText"
        android:layout_weight="1"
        android:hint="@string/name_hint" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="getScore"
        android:id="@+id/myButton"
        android:text="@string/button_label" />

getIntentとgetStringExtra

Activity間のやりとりは、intentを用いて呼び出します。putExtraで、データを引き渡します。

            Intent intent = new Intent(this, MyResult.class);
            intent.putExtra(EXTRA_MYNAME, myName);
            startActivity(intent);

MyResult.java

        Intent intent = getIntent();
        String myName = intent.getStringExtra(MyForm.EXTRA_MYNAME);
        TextView nameLabel = (TextView) findViewById(R.id.nameLabel);
        nameLabel.setText(myName + "の点数は...");

findViewByIdとgetText().toString()

エラー処理にはsetErrorを使います。その他、ToastやDialogなどがあります。

public void getScore(View view){
        // edit text取得
        EditText myEditText = (EditText)findViewById(R.id.myEditText);
        String myName = myEditText.getText().toString().trim();
        if (myName.equals("")){
        /*
        setError, toast, dialog
         */
         myEditText.setError("Please enter your name!");
        } 

Layout->New->Activityで、新しいActivityを作成できます。
%e7%84%a1%e9%a1%8c

Java new Random()によるおみくじ

public void getOmikuji(View view) {
        // TextViewの取得
        TextView tv = (TextView) findViewById(R.id.myTextView);
        String[] results = {
                "大吉",
                "吉",
                "凶"
        };
        // 乱数の生成
        Random randomGenerator = new Random();
        int num = randomGenerator.nextInt(results.length); // 0-2
        // 結果の表示
        //        String result = Integer.toString(num);
        tv.setText(results[num]);
    }

テーマの変更
rsc -> values -> styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

activity_main.xmlはstrings.xmlへの記載することが推奨されています。
rsc -> values -> strings.xml

<resources>
    <string name="app_name">おみくじアプリ</string>

    <string name="omikuji_label">あなたの運勢は...</string>
    <string name="score_label">____</string>
    <string name="button_label">おみくじを引く</string>
</resources>

Android Studioが重すぎるとき


上の画面を作るのに6時間程度費やしました。
さて、studioが重すぎる時の対応案です。コンパイラであるgradleに起因している可能性があります。
https://developer.android.com/studio/build/index.html

1.Prgram Files > Android > Android Studio > bin > studio64.exe.vmpoptions
編集
※アクセス権がない場合は、アクセス権を変更してください。

-Xms1024m
-Xmx2048m
-XX:MaxPermSize=512m

2. c:\users\name\AndroidStudioProjects\MyAppnameApp\gradle.property 
コメントアウト・追記

org.gradle.daemon=true
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.parallel=true
org.gradle.configureondemand=true

3.settingでgradleをオフラインモードに変更

4.Setting -> Editor -> General -> Code Completion
autopop系は全てチェックボックスを外す

コンパイルの時間やIDEの操作がモチベーションを左右しますね。