くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

【Android】コンテンツ プロバイダ(ContactsProvider)を使って連絡先から誕生日と名前を取得する

Androidの開発をしていて、連絡先から誕生日を取得して、ごにょごにょする必要があったので、その際の備忘録。
コンテンツプロバイダ関連って余り情報がないので、こまった。。

連絡先を扱うには、パーミッションが必要です

今回は読み込みだけなので、以下をAndroidManifest.xmlに追加

<uses-permission android:name="android.permission.READ_CONTACTS"/>

検索・取得のはこんな感じ

//取得するカラムをは、名前とIDと誕生日
String[] projection = new String[]{
        ContactsContract.Contacts.DISPLAY_NAME,
        ContactsContract.CommonDataKinds.Event.CONTACT_ID,
        ContactsContract.CommonDataKinds.Event.START_DATE
};
// 検索条件で、Event.TYPEがTYPE_BIRTHDAYのみに絞り込む
String selection =
        ContactsContract.Data.MIMETYPE + "= ? AND " +
                ContactsContract.CommonDataKinds.Event.TYPE + "=" +
                ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY;
String[] selectionArgs = new String[]{
        ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE
};
// ソートの指定はなし
String sortOrder = null;

Cursor cursor = context.getContentResolver().query(
        ContactsContract.Data.CONTENT_URI,
        projection,
        selection,
        selectionArgs,
        sortOrder);

// あとは、whileで結果を取得
while (cursor.moveToNext()) {
    int nameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
    String name = cursor.getString(nameIndex);

    int birthIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Event.START_DATE);
    String birthDay = cursor.getString(birthIndex);
}

以上!!

参考にしたサイト様

AndroidのActivityを透過させて表示させるスタイル

画像を拡大表示するときに背景を透明にしたいなと思ったので、調べたときの備忘録

ほぼ、Nyanさんの記事の通り!

styles.xmlに半透明になるスタイルを追加して、AndroidManifest.xmlでactivityに設定するだけ

まずは、styles.xmlに以下のスタイルを追加する。

SupportLibraryのAppCompatActivityを使うかどうかで若干違うので注意

Activityの場合

Activityの場合は、参考サイトの通り、「android:style/Theme.Translucent」を継承

<resources>
    <!-- 半透明背景設定 -->
    <drawable name="transparameter">#7f000000</drawable>
    <style name="Theme.TranslucentBackground" parent="android:style/Theme.Translucent">
        <item name="android:windowBackground">@drawable/transparameter</item>
        <item name="android:windowNoTitle">true</item>
    </style>
</resources>

AppCompatActivityの場合

AppCompatActivityの場合は、「style/AppTheme.NoActionBar」とかを継承

<resources>

    <!-- 半透明背景設定 -->
    <drawable name="transparameter">#7f000000</drawable>

    <style name="Theme.TranslucentBackground" parent="style/AppTheme.NoActionBar">
        <item name="android:windowBackground">@drawable/transparameter</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:colorBackgroundCacheHint">@null</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowAnimationStyle">@android:style/Animation</item>
    </style>
</resources>

以上!!簡単!!

参考人したサイト様

Herokuでpushした際に認証失敗してDeployできなかったときの対処方法(heroku auth:tokenを使う)

久々にWindowsでHerokuにデプロイしようと思ったら上手く行かなかったので、その備忘録。

git push heroku masterをしたら、認証に失敗した

認証に失敗して、以下のメッセージが表示。。
同じID/Passでは、Webのコンソールにはアクセスできるのに。。

remote: !       WARNING:
remote: !       Do not authenticate with username and password using git.
remote: !       Run `heroku login` to update your credentials, then retry the git command.
remote: !       See documentation for details: https://devcenter.heroku.com/articles/git#http-git-authentication
fatal: Authentication failed for 'https://git.heroku.com/xxxxxxxxx.git/'

アクセストークンを利用するとうまくいくよう

以下の記事にある通り、試してみたらうまくいった!!

qiita.com

以下、引用。

heroku auth:token
と入力して、続けて表示された文字列をコピーします。
同じようにgit push heroku masterとした時に、以下のように対応します。

Username for 'https://git.heroku.com': (空エンター)  
Password for 'https://git.heroku.com': コピーした文字列

以上!!

参考にしたサイト様

AndroidとDagger2でDIしてみる

前々から気になっていたDIライブラリのDaggerを使ってみたので、その備忘録。

登場人物はこんな感じ

DIといえば、Springな人なので、イメージを掴むのが一苦労だった。。

全体像がよくわからないので、図にしてみた。

こんな感じ。

f:id:wannabe-jellyfish:20170730214305p:plain

使い方

build.gradleのdependenciesに依存関係を追加すればOK

dependencies {
    // Dagger
    compile 'com.google.dagger:dagger:2.11'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.11'
    provided 'javax.annotation:jsr250-api:1.0'
}

各登場人物のTips

@Inject

コンストラクタインジェクションもできる

public class Sample {
  @Inject
  public Sample(Aclass aCls) {
    // aClsがInjectionされてSampleクラスのインスタンスを生成
  }
}

@Provide

具象クラスであれば、@Provideはいらない

具象クラスが特定できるオブジェクトは、@Provideのメソッドが不要(DIする意味ないかもしれないが。。。)

インターフェースを切っていたり、アブストラクトクラスに対して@Injectを付与している場合は必要

@Provideのメソッドも引数が取れる

こんな感じ。ただし、引数に渡すクラスの@Provideが用意されている必要がある

@Module
public class AppModule {
  @Provide
  public Aclass provideAclass(Bclass bCls) {
     return ・・・
  }

  @Provide
  public Bclass provideBclass() {
    //これがprovideAclass()で使われる
  }
}

@Module

@Moduleのついたクラスにコンストラクタ引数が使える

こんな感じ。

@Module
public class AppModule {
  public AppModule(ArgClass argCls) {
  }
}

ただし、Componentを生成するときに引数を指定が必要

public class MainClass {
  public MainClass() {
    DIComponent diComponent = DaggerDIComponent
      .builder()
      .appModule(new AppModule(this))  // <- ここで指定
      .build();
  }
}

デフォルトコンストラクタのみの@Moduleのクラスだと、builder()でModuleの指定を省略できる

@Component

@Componentで用意するのは、エントリーポイントとなるクラスだけ

例えば、こんな感じ担っている場合。

public class Aclass() {
  @Inject Bclass bCls;
}

public class Bclass() {
  @Inject Cclass cClas;
}

Aclassに対する@ComponentがあればOK。指定したクラスを起点に、内部のフィールドを辿ってくれる。

以上!!

参考にしたサイト様

AndroidでMaterial Designボタンに変更するスタイル

Androidアプリを作っていて、マテリアルデザインのボタンにしたいなと思い、色々調べた備忘録。

Raised Button

f:id:wannabe-jellyfish:20170729233133p:plain

styles.xmlにスタイルを用意する

用意するスタイルはこんな感じ。

<style name="AppTheme.RaisedButton" parent="Theme.AppCompat.Light">
    <item name="colorControlHighlight">#FFD464</item>
    <item name="colorButtonNormal">#FBA848</item>
    <item name="android:textColor">#FFFFFF</item>
</style>

Buttonにスタイルを適用

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Raised Button" 
    android:theme="@style/AppTheme.RaisedButton"
    />

Flat Button

f:id:wannabe-jellyfish:20170729234307p:plain

styles.xmlにスタイルを用意する

用意するスタイルはこんな感じ。

<style name="AppTheme.FlatButton" parent="Theme.AppCompat.Light">
    <item name="colorControlHighlight">#FFD464</item>
    <item name="android:textColor">#FBA848</item>
</style>

Buttonにスタイルを適用

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Flat Button"
    android:theme="@style/AppTheme.FlatButton"
    style="@style/Widget.AppCompat.Button.Borderless"
    />

以上!!

参考にしたサイト様

AndroidStudioで開発をはじめるときにすること~パッケージ構成&共通クラス編~

いろいろやっているとAndroidアプリを開発しはじめるときにいつもやることを忘れるので、その備忘録。その2

環境
  1. Android Studio: 2.3.3
  2. Gradle: 3.3
  3. Android Plugin for Gradle: 2.3.3
  4. Java8

パッケージ構成はこんな感じ

<root_package>/
├── activity              ... Activity
│   └── MainActivity.java
├── di                    ... DI関係。DaggerのComponentとか
├── dialog                ... DialogFragment
├── entity                ... OrmaのModels
├── fragment              ... Fragment
├── repository            ... OrmaのHelper
├── util                  ... Utitly関係
├── widget                ... UI部品
└── AppApplication.java   ... Applicationクラス
一括作成bashコマンド
mkdir -p activity di dialog entity fragment repository util widget

共通クラスはこんな感じ

BaseActivity

import android.os.Bundle;
import android.support.annotation.LayoutRes;
import android.support.v7.app.AppCompatActivity;

import butterknife.ButterKnife;

public abstract class BaseActivity extends AppCompatActivity {

    private AppComponent appComponent;

    protected static void start(@NonNull AppCompatActivity activity, @NonNull Intent intent) {
        activity.startActivity(intent);
        // activity.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left);
    }

    @NonNull
    protected AppComponent getComponent() {
        if (appComponent == null) {
            AppApplication appApplication = (AppApplication) getApplication();
            appComponent = appApplication.getAppComponent();
        }

        return appComponent;
    }

    @LayoutRes
    protected abstract int layoutId();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(layoutId());
        ButterKnife.bind(this);
    }
}

BaseFragment

import android.os.Bundle;
import android.support.annotation.LayoutRes;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import butterknife.ButterKnife;

public abstract class BaseFragment extends Fragment {

    @LayoutRes
    protected abstract int layoutId();

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(layoutId(), container, false);
        ButterKnife.bind(this, view);
        return view;
    }
}

AppApplication

import lombok.Getter;
public class AppApplication extends Application {

    @Getter
    AppComponent appComponent;

    @Override
    public void onCreate() {
        super.onCreate();

        // Dagger
        appComponent = DaggerAppComponent.builder()
                .appModule(new AppModule(this))
                .build();
    }
}

Dagger関連

di.AppModule

@Module
public class AppModule {

    private Context context;

    public AppModule(Application app) {
        context = app;
    }

    @Provides
    public Context provideContext() {
        return context;
    }

    @Singleton
    @Provides
    public OrmaDatabase provideOrmaDatabase(Context context) {
        return OrmaDatabase.builder(context)
                .writeOnMainThread(AccessThreadConstraint.WARNING)
                .build();
    }

    @Singleton
    @Provides
    public MyRepository provideMyRepository(OrmaDatabase orma) {
        return new MyRepositoryImpl(orma);
    }
}

di.AppComponent

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {

    void inject(MainActivity activity);
}

Orma関連

MyRepository

@Singleton
public class MyRepositoryImpl implements MyRepository {

    OrmaDatabase orma;

    @Inject
    public PersonRepositoryImpl(OrmaDatabase orma) {
        this.orma = orma;
    }

    @NonNull
    @Override
    public List<PersonEntity> findAll() {
        return orma.selectFromPersonEntity().toList();
    }
}

サンプル

MainActivity

public class MainActivity extends BaseActivity {
    @Inject
    MyRepository myRepo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getComponent().inject(this);
    }
}

AndroidStudioで開発をはじめるときにすること~build.gradle編~

いろいろやっているとAndroidアプリを開発しはじめるときにいつもやることを忘れるので、その備忘録。

環境
  1. Android Studio: 2.3.3
  2. Gradle: 3.3
  3. Android Plugin for Gradle: 2.3.3
  4. Java8
使うライブラリ
  1. Gradle Retrolambda PluginAndroidでJava8のラムダ式がつかえるようになるやつ
  2. LombokJavaのボイラープレートコードをシンプルにしてくれるJavaのライブラリ
  3. Butter KnifeAndroidの View Injection ライブラリ
  4. Android-OrmaAndroid用のO/R Mapper
  5. Dagger … DIフレームワーク
  6. RxAndroidAndroidのリアクティブプログラミングライブラリ
  7. Picasso … 画像読み込みライブラリ

build.gradleを整える

Retrolambdaの導入

  • build.gradle
 buildscript {
     repositories {
         jcenter()
+        mavenCentral()
     }
     dependencies {
         classpath 'com.android.tools.build:gradle:2.3.3'
+        classpath 'me.tatarka:gradle-retrolambda:3.6.1'
     }
 }
 
 allprojects {
     repositories {
         jcenter()
+        mavenCentral()
     }
 } 
  • app/build.gradle
 apply plugin: 'com.android.application'
+apply plugin: 'me.tatarka.retrolambda'
 
 android {
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
 }

Lombokの導入

  • app/build.gradle
 dependencies {
+    provided 'org.projectlombok:lombok:1.16.18'
 }

Butter Knifeの導入

  • app/build.gradle
 dependencies {
+    compile 'com.jakewharton:butterknife:8.7.0'
+    annotationProcessor 'com.jakewharton:butterknife-compiler:8.7.0'
 }

RxAndroidの導入

  • app/build.gradle
 dependencies {
+    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
+    compile 'io.reactivex.rxjava2:rxjava:2.1.0'
 }

Ormaの導入

  • app/build.gradle
 dependencies {
+    annotationProcessor 'com.github.gfx.android.orma:orma-processor:4.2.5'
+    compile 'com.github.gfx.android.orma:orma:4.2.5'
 }

Daggerの導入

  • app/build.gradle
 dependencies {
+    compile 'com.google.dagger:dagger:2.11'
+    annotationProcessor 'com.google.dagger:dagger-compiler:2.11'
+    provided 'javax.annotation:jsr250-api:1.0'
 }

自分用の変更①: buildTypeにdebugを追加

  • app/build.gradle
 android {
     buildTypes {
+        debug {
+            applicationIdSuffix '.debug'
+            versionNameSuffix 'a'
+        }
         release {
             minifyEnabled false
             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
         }
     }

自分用の変更②: apkのファイル名を変更

  • app/build.gradle
 android {
+    android.applicationVariants.all { variant ->
+        if (variant.buildType.name == "release") {
+            variant.outputs.each { output ->
+                def newName = "${defaultConfig.applicationId}_ver${defaultConfig.versionName}_${variant.buildType.name}.apk"
+                output.outputFile = new File(output.outputFile.parent, newName)
+            }
+        }
+    }
 }

自分用の変更③: Support Libraryのバージョンを変数化

  • app/build.gradle
+def support_lib_ver = '25.3.1'
 dependencies {
-    compile 'com.android.support:appcompat-v7:25.3.1'
-    compile 'com.android.support:design:25.3.1'
+    compile "com.android.support:appcompat-v7:${support_lib_ver}"
+    compile "com.android.support:design:${support_lib_ver}"
 }