くらげになりたい。

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

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}"
 }

Unityでよく使うスクリプト集(C#版)【随時更新】

Unityでよく調べなおすので、個人的なチートシート

Unityでブラウザリンクを開く

string url = "http://wannabe-jellyfish.hatenablog.com/";
Application.OpenURL(url);

参考にしたサイト様

Django/PythonでCSVファイルをアップロード(.csv)したり、ダウンロード(.csv)したり、ダウンロード(.zip)したりする方法

Django/Pytonを使ってCSVファイルをあれこれするために、いろいろ調べたので、その際の備忘録。

環境はDjango1.10.1とPython2.7

CSVファイルの扱いは、基本的にimport csvのパッケージ

okadateさんのQiita記事にあるとおり、PythonでのCSVファイルの操作は以下な感じ。

import csv

# 読み込み
with open('some.csv', 'r') as f:
  reader = csv.reader(f)
  header = next(reader)  # ヘッダーを読み飛ばしたい時
  for row in reader:
    print row          # 1行づつ取得できる

# 書き込み
with open('some.csv', 'w') as f:
  writer = csv.writer(f, lineterminator='\n') # 改行コード(\n)を指定しておく
  writer.writerow(list)     # list(1次元配列)の場合
  writer.writerows(array2d) # 2次元配列も書き込める

Django上でこれらを行うときは、リクエストとレスポンスも絡んでくる。

アップロードされたCSVファイルを読み込んで処理する

アップロードされたCSVファイルを読み込む場合は、open()request.FILES['file']になる感じ。

import csv
import traceback
from django.shortcuts import render

def upload_file(request):
  try:
    csv_file = request.FILES['file']

    reader = csv.reader(req_file)
    header = next(reader)

    for csv_row in reader:
      print csv_row 

    csv_file .close()
  except:
    traceback.format_exc()

  return render(request, "index.html")

CSVファイルをダウンロードする

基本的には、csv.writerを使って、`responseに書き込んでいく感じ。
ただ、日本語の場合は、ファイル名とファイルの中身の文字コードに注意!!

  • ファイル名が日本語の場合、UTF8でURLエンコードする
  • ファイルの中身が日本語の場合、環境に合わせる。(例はWindows用としてSJISに変換)
import csv
import urllib
from django.http.response import HttpResponse

def download_csv(request):
  filename = urllib.quote((u'CSVファイル.csv').encode("utf8"))

  response = HttpResponse(content_type='text/csv')  
  response['Content-Disposition'] = 'attachment; filename*=UTF-8\'\'{}'.format(filename)

  writer = csv.writer(response)

  writer.writerow(map(lambda n:toSJIS(n), [u'概要', u'詳細']))
  writer.writerow(map(lambda n:toSJIS(n), [u'ああああ', u'いいい']))
  writer.writerow(map(lambda n:toSJIS(n), [u'かかかか', u'ききき']))

  return response

def toSJIS(s=""):
  u'{}'.format(s).encode("sjis")

複数のCSVファイルをzipにまとめてダウンロードする

こちらも基本はcsv.writerを使ってzip_fileに書き込み、zip_fileの内容をresponseに設定する感じ。
注意点はこちらも文字コード周り。。。

  • ZIPファイル名が日本語の場合、UTF8でURLエンコードする
  • CSVファイル名が日本語の場合、環境に合わせる。URLエンコードは不要(例はWindows用としてSJISに変換)
  • CSVファイルの中身が日本語の場合、環境に合わせる。(例はWindows用としてSJISに変換)
import csv
import urllib
import zipfile
from django.http.response import HttpResponse

def download_csv_zip(request):
  #### 書き込むzipファイルの準備
  memory_file = BytesIO()
  zip_file = zipfile.ZipFile(memory_file, 'w')

  #### CSVファイルの書き込み。1ファイル目
  csv_file1 = BytesIO()
  filename1 = (u'CSVファイル1.csv').encode("sjis")
  writer1 = csv.writer(csv_file1)

  writer1.writerow(map(lambda n:toSJIS(n), [u'概要', u'詳細']))
  writer1.writerow(map(lambda n:toSJIS(n), [u'ああああ', u'いいい']))

  ## CSVファイルの内容をzip_fileに書き込む。
  zip_file.writestr(filename1, csv_file1.getvalue())
  csv_file1.close()

  #### CSVファイルの書き込み。2ファイル目
  csv_file2 = BytesIO()
  filename2 = (u'CSVファイル2.csv').encode("sjis")
  writer2 = csv.writer(csv_file2)

  writer2.writerow(map(lambda n:toSJIS(n), [u'概要', u'詳細']))
  writer2.writerow(map(lambda n:toSJIS(n), [u'ああああ', u'いいい']))

  ## CSVファイルの内容をzip_fileに書き込む。
  zip_file.writestr(filename2, csv_file2.getvalue())
  csv_file2.close()
  

  #### zipファイルの内容をreponseに設定
  zip_file.close()
  zip_filename = urllib.quote((u'CSVファイル(複数).zip').encode("utf8"))
  response = HttpResponse(memory_file.getvalue(), content_type='application/zip')
  response['Content-Disposition'] = 'attachment; filename*=UTF-8\'\'{}'.format(urllib.quote(zip_file_name))

  return response

def toSJIS(s=""):
  u'{}'.format(s).encode("sjis")

以上!!

Python、さくっと書くのはいいんだけど、静的型付け言語が好きなので、結構困る。。。

参考にしたサイト様