Upgrade to Pro — share decks privately, control downloads, hide ads and more …

少し幸せにする技術

Bcd7ba3b99b88a1d906961169b467b0a?s=47 kamedon
March 09, 2017

 少し幸せにする技術

DroidKaigi 2017 3/9 Room4 18:00~
Kamedon

リンクが有効なバージョン
https://www.slideshare.net/kamedon39/ss-72985127

Bcd7ba3b99b88a1d906961169b467b0a?s=128

kamedon

March 09, 2017
Tweet

Transcript

  1. গ͠޾ͤʹͳΔٕज़ DroidKaigi 2017 3/9 18:00~ Kameron

  2. ॕʂॳొஃ

  3. ࣗݾ঺հ

  4. ϓϩϑΟʔϧ • Χϝυϯ • Kotlin޷͖Ͱ͢ • ΫϥεϝιουͰΞϯυϩΠυ ͷΞϓϦ։ൃ΍ͬͯ·͢ • ϘʔυήʔϜ͕޷͖Ͱ͢

  5. None
  6. ొஃͷ͖͔͚ͬ • 2.3࣌୅ɺEclipse࣌୅ͷݹ͍৘ใ͕ώοτ͢Δ • ೖ໳ॻ͕ຊ౰ʹೖ໳ॻ • ಈ͘ίʔυ͸ॻ͍ͯ͋Δ͕ɺϓϩδΣΫτͰ
 ࢖͏ͨΊʹඞཁͳ͜ͱ͸͋·Γॻ͍͍ͯͳ͍ • ࣍ͷεςοϓͷΩʔϫʔυͱͯ͠


    ৄࡉʹऔΓѻ͍·ͤΜ • ొஃऀͷࢀՃඅແྉɻ • Ԡื͚ͩͰ΋׬ച࣌΋ߪೖՄೳ • μϝ΋ͱͰԠืͯ͠Έ·ͨ͠
  7. ͜ͷൃදͰ޾ͤʹͳΓͦ͏ͳਓ • ॳ৺ऀ͔Βதڃऀʹεςοϓ͠Α͏ͱ͍ͯ͠Δํ • Android։ൃΛ΋ͬͱָʹ͢Δ • Android ։ൃͰͭ·͖ͮʹ͘͘͢Δ • ΞΧ΢ϯτఀࢭ͞Εͳ͍Α͏ʹ͢Δ

  8. ΞδΣϯμ • ٯҾ͖ܗࣜͰ঺հ͍͖ͯ͠·͢ • Android Studio • Build.gradle • σόοά

    • OS,୺຤ • ProGuard • Google Play Console
  9. Android Studioฤ

  10. Android Studioฤ (ver2.3) • Jetbrains੡IDE • ҰੲEclipseͱ͍͏΋ͷ͋Γ͚Γ • ADTͱ͍͏ϓϥάΠϯ͕͕͋ͬͨɺ
 αϙʔτ͕੾Ε͍ͯΔͷͰɺ


    ඞͣAndroid StudioΛ࢖͓͏
  11. ଞͷIDEͱγϣʔτΧοτ͕
 ҧ͏ͷͰɺΠϥΠϥ͖ͯͨ͠ • Android Studio ࠷ڧίϚϯυ
 Find Action • Mac:

    ⌘ ⇧ A • Windows: Ctrl Shift A
 • ίϚϯυΛݕࡧͰ͖ɺγϣʔτΧοτ·ͰΘ͔Δ • ઃఆͰKeymapΛมߋ͢Δͱ޷ΈͷઃఆʹͰ͖Δ
  12. ಛఆϑΝΠϧʹ
 ΋ͬͱ؆୯ʹͱͼ͍ͨ • Android Studio ࠷ڧίϚϯυʹ͙࣍
 Search Everywhere • Mac:

    ⇧ ⇧ • Windows:Shift Shift • ϑΝΠϧ໊Λ؆୯ʹݕࡧͰ͖Δ
  13. ϑΥʔϚοτΛἧ͑Δͷ͕
 ΊΜͲ͍ • Save ActionsͰอଘͰࣗಈͰϑΥʔϚοτΛ ἧ͑Δ

  14. ΞϯΠετʔϧɺΠϯετʔϧ ͕ΊΜͲ͍͘͞ • Plugin ADB IDEA
 $USM4IJGU"
 ϙοϓΞοϓ͕ͰΔ

  15. ςετͰ௨ͬͯͳ͍ͱ͜ΖΛ஌ Γ͍ͨ public class CalcUtil {
 public static int mod(int

    x, int y) {
 if (y == 0) {
 throw new IllegalArgumentException("y != 0");
 }
 return x % y;
 }
 }
  16. public class CalcUtilTest {
 
 @Test
 public void 余りのテスト() {

    
 Assert.assertThat(3,Is.is(CalcUtil.mod(11, 4)));
 }
 } ςετͰ௨ͬͯͳ͍ͱ͜ΖΛ஌ Γ͍ͨ Z͕ͷέʔε͕ൈ͚͍ͯΔ
  17. ςετͰ௨ͬͯͳ͍ͱ͜ΖΛ஌ Γ͍ͨ 3VO`5FTUJOʜ`XJUI$PWFSBHF Λ࣮ߦ

  18. Build.gradle ฤ

  19. Build.gradleฤ • ΞϓϦͷجຊ৘ใΛઃఆ • ੲ͸͢΂ͯAndroidManifestͰ؅ཧ͍͕ͯͨ͠ɺ
 Ұ෦ͷઃఆ͕Build.gradleͰ؅ཧ͢ΔΑ͏ʹͳͬͨ • AndroidManifest: ύʔϛογϣϯ΍ϖʔδɺ
 ಈ࡞ͷઃఆ

    • Build.gradle: όʔδϣϯɺϥΠϒϥϦɺ؀ڥͷઃఆ
  20. ։ൃ൛ͱϦϦʔε൛ͬͯڞଘͰ ͖Δʁ • Ϗϧυ όϦΞϯτͱϓϩμΫτϑϨʔόʔΛ ࢖͏ͱͰ͖·͢ʂ • ύοέʔδ໊͕ಉ͔ͩ͡ΒڞଘͰ͖·ͤΜ • σόοΫͱϦϦʔε൛ͷύοέʔδ໊͕มΘ

    ΔΑ͏ʹSuffixΛ͚ͭͯ͋͛·͠ΐ͏
  21. όʔδϣϯίʔυͱόʔδϣϯ ໊؅ཧ͕ΊΜͲ͍͘͞ buildTypes {
 release {}
 debug {
 applicationIdSuffix ".debug"


    }
 }
 productFlavors {
 demo {
 applicationIdSuffix ".demo"
 }
 full {
 applicationIdSuffix ".full"
 }
 } ϓϩμΫτϑϨʔόʔ ϏϧυόϦΞϯτ BQQCVJMEHSBEMF \QLH^\'MBWPS^\#VJME5ZQF^ \QLH^EFNPEFCVH
  22. • Ϗϧυ όϦΞϯτͱϓϩμΫτϑϨʔόʔͰ
 ಉ໊ͳΒϏϧυόϦΞϯτͷ΄͏͕༏ઌ • BuildConfigϑΝΠϧ͕Ͱ͖Δ ։ൃͱ੡඼൛Ͱఆ਺Λ෼͚͍ͨ

  23. buildTypes {
 release {
 buildConfigField "String", "ENDPOINT", "\"https://hoge.com\" "
 }


    debug {
 applicationIdSuffix ".debug"
 buildConfigField "String", "ENDPOINT", "\"https://localhost\" "
 }
 }
 
 productFlavors {
 demo {
 buildConfigField "boolean", "DEMO", "true"
 applicationIdSuffix ".demo"
 }
 full {
 buildConfigField "boolean", "DEMO", "false"
 applicationIdSuffix ".full"
 }
 } ։ൃͱ੡඼൛Ͱఆ਺Λ෼͚͍ͨ
  24. buildTypes {
 release {
 buildConfigField "String", "ENDPOINT", "\"https://hoge.com\" "
 }


    debug {
 applicationIdSuffix ".debug"
 buildConfigField "String", "ENDPOINT", "\"https://localhost\" "
 }
 }
 
 productFlavors {
 demo {
 buildConfigField "boolean", "DEMO", "true"
 applicationIdSuffix ".demo"
 }
 full {
 buildConfigField "boolean", "DEMO", "false"
 applicationIdSuffix ".full"
 }
 } ։ൃͱ੡඼൛Ͱఆ਺Λ෼͚͍ͨ
  25. ։ൃ൛ͱϦϦʔε൛Ͳ͔ͬͪͳ ͷ͔Θ͔Γ΍͍ͨ͘͢͠ • ϦιʔεϑΝΠϧɺιʔείʔυ΋Ϗϧυ όϦΞϯτ
 ͱϓϩμΫτϑϨʔόʔʹΘ͚ΒΕ·͢ɻ
 ʢ༏ઌॱҐ͸্͔Βॱ൪ʣ • src/demoDebug/ʢϏϧυόϦΞϯτ ϑϨʔόʔʣ

    • src/debug/ʢϏϧυόϦΞϯτʣ • src/demo/ʢϑϨʔόʔʣ • src/main/ʢϝΠϯ ʣ
  26. ։ൃ൛ͱϦϦʔε൛Λ Θ͔Γ΍͍ͨ͘͢͠ • ྫ͑͹ຊ൪ͱ։ൃΞϓϦ໊Λม͑ͯΈΔ • app/src/main/res/values/strings.xmlΛ
 app/src/debug/res/values/strings.xmlʹ
 ίϐʔɺฤू͢Δ • ಉ͡৔ॴʹ࡞੒͢Δͱ্ॻ͖͞ΕΔ

    <string name=“app_name">Debug</string>
  27. ϏϧυόϦΞϯτͱϓϩμΫτϑ Ϩʔόʔ࢖͍෼͚͕Θ͔Βͳ͍ • ϏϧυόϦΞϯτ: ؀ڥͷઃఆ • ຊ൪αʔόʔͱ։ൃαʔόʔͷΞυϨε • ຊ൪༻ॺ໊ɺ։ൃ༻ॺ໊ •

    ϓϩμΫτϑϨʔόʔɿΞϓϦͷৼΔ෣͍ • σόοΫϞʔυ: ON/OFF • ແྉ൛/՝ۚ൛: ON/OFF
  28. όʔδϣϯίʔυͱόʔδϣϯ ໊؅ཧ͕ΊΜͲ͍͘͞ def major = 1
 def minor = 0


    def patch = 0
 def build = 0
 
 android {
 defaultConfig {
 versionCode major * 10000 + minor * 1000 + patch * 100 + build
 versionName "${major}.${minor}.${patch}"
 }
 } WFSTJPO/BNFͱWFSTJPO$PEF
 Λ࿈ಈ͢ΔΑ͏ʹ͢Δ ։ൃऀ͸WFSTJPO/BNFΛ্͍͛ͨ (PPHMF1MBZ͸ɺWFSTJPO$PEF্͕͕ͬͯΕ͹Α͍
  29. ॺ໊ͷ؅ཧͲ͏ͨ͠Βྑ͍ͷʁ • ॺ໊Λbuild.gradleʹϕλॻ͖ • Private RepositoryͳͲͳΒ༗ޮ • CI͔Β΋ѻ͍΍͍͢ • ϑΝΠϧʹॻ͖ग़͢

    • gitͰແࢹઃఆ͠ɺ伴͸ผ؅ཧ
  30. ॺ໊Λϕλॻ͖ signingConfigs {
 release {
 storeFile file(“./filepath”)
 keyAlias “test”
 storePassword

    “test”
 keyPassword “test”
 }
 }
  31. ॺ໊৘ใΛϑΝΠϧʹॻ͖ग़͢ • keystore.properties Λ࡞੒ storePassword=myStorePassword
 keyPassword=mykeyPassword
 keyAlias=myKeyAlias
 storeFile=myStoreFileLocation

  32. ॺ໊৘ใΛϑΝΠϧʹॻ͖ग़͢ • build.gradleͰಡΉ͜Ή signingConfigs {
 debug {
 def keystorePropertiesFile =

    rootProject.file("keystore.properties")
 def keystoreProperties = new Properties()
 keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 
 keyAlias keystoreProperties['keyAlias']
 keyPassword keystoreProperties['keyPassword']
 storeFile file(keystoreProperties['storeFile'])
 storePassword keystoreProperties['storePassword']
 }
 }
  33. σόοάฤ

  34. σόοάฤ • ఻Ոͷๅ౛ϓϦϯτσόοά • ϝϞϦϦʔΫ΍௨৴पΓ͕σόοάͮ͠Β͍

  35. ੡඼൛ͷͱ͖͸LogΛग़ͨ͘͠ ͳ͍ • JakeWharton/timberΛ࢖͏ • Debug͚ͩϩάΛग़͢͜ͱ͕؆୯ • ϩάΛԿͰग़͔͢ม͑Δͷ΋؆୯
 if (BuildConfig.DEBUG)

    {
 Timber.plant(Timber.DebugTree())
 }
 Timber.d(“test”,”test”)
  36. ௨৴෦෼ͷσόοΫ͕ͣ͠Β͍ • facebook/stethoΛೖΕͯɺChomeͰσόοά • ιʔείʔυʹೖΕΔඞཁ͋Γ • mitmproxyΛೖΕͯɺωοτϫʔΫΛ؂ࢹ • ιʔείʔυʹೖΕΔඞཁͳ͠ •

    pythonίʔυͰendpointΛม͑ͨΓͰ͖·͢
  37. TUFUIP

  38. NJUNQSPYZ

  39. ϝϞϦϦʔΫͷσόοά͕͠Μ Ͳ͍ • square/leakcanaryΛ࢖͏ͱ؆୯ • Applicationʹॻ͚ͩ͘Ͱɺ
 ϦʔΫ࣌ʹ௨஌Λग़ͯ͘͠ΕΔ

  40. Logͷ͍ͤͰUnit TestͰΤϥʔ ͕ͰΔ • Log͚ͩͳΒɺClassLoaderͷ࢓૊ΈΛ࢖ͬͯLogΛ্ॻ͖͢Δ
 app/src/test/java/android/util/Log.javaʹҎԼΛஔ͘ public class Log {


    public static int v(String tag, String msg) { return 0; }
 public static int v(String tag, String msg, Throwable tr) { return 0; }
 public static int d(String tag, String msg) { return 0; }
 public static int d(String tag, String msg, Throwable tr) { return 0; }
 public static int i(String tag, String msg) { return 0; }
 public static int i(String tag, String msg, Throwable tr) { return 0; }
 public static int w(String tag, String msg) { return 0; }
 public static int w(String tag, String msg, Throwable tr) { return 0; }
 public static int w(String tag, Throwable tr) { return 0; }
 public static int e(String tag, String msg) { return 0; }
 public static int e(String tag, String msg, Throwable tr) { return 0; }
 }
  41. ProGuradฤ

  42. ProGuard • ηΩϡϦςΟతʹ࠷௿ݶϦϦʔε࣌ʹඞͣઃ ఆ͢Δ • ΞϓϦαΠζͷ࡟ݮ • ؾٳΊ೉ಡԽ public class

    MainActivity extends c {
 private TextView m;
 public MainActivity() {}
 protected void onCreate(Bundle var1) {
 super.onCreate(var1);
 this.setContentView(2130968603);
 this.m = (TextView)this.findViewById(2131427415);
 this.m.setText("hello world");
 }
 }
  43. 64kϝιου͔͠Ͱ͖ͳ͍ͷʁ • 64kϝιου͸ϏϧυͰ͖·ͤΜ • ProGuardΛ͔͚Δ͜ͱͰϝιου਺ͷ࡟ݮ • ͦΕͰ΋ͩΊͳ৔߹͸ɺMultidexΛ༻͍Δ ͜ͱͰ64kͷนΛ௒͑ΒΕ·͢

  44. ProGuardΛ͔͚ΔͱΤϥʔʹ ͳΔɻมͳ׼͕Ͱ͖ͯͨɻ • ProGuard͕ͯ͠Δ͜ͱΛཧղ͢Δ • ະ࢖༻ͷϝιου࡟আ • Ϋϥε໊ɺϝιουΛa,bͳͲͷϦωʔϜ • ϦϑϨΫγϣϯΛ࢖༻͍ͯ͠Δͱ͜ΖͰ


    ΤϥʔʹͳΔ • ͦͷ෦෼͸KeepΛ࢖༻ͯ͠ɺϦωʔϜͤ͞ ͳ͍ɺ࡟আͤ͞ͳ͍
  45. ϦϦʔεͷͱ͖͚ͩProGuard ͔͚ΔͱυΩυΩ͢Δ • ։ൃதʹ΋ProGuardΛ͔͚Δͱ҆৺ • Ϗϧυ͕஗͘ͳΔͷ͕ܽ఺ • ։ൃ࣌͸ɺίʔυ࡟ݮ͸͢Δ͕ɺϦωʔϜ͸͠ͳ͍΄͏͕ Α͍ buildTypes

    {
 debug {
 minifyEnabled true
 useProguard false
 proguardFiles getDefaultProguardFile('proguard- android.txt'),
 'proguard-rules.pro'
 }
 }
  46. ΫϥογϡϨϙʔτ͕೉ಡԽ͞ Ε͍ͯͯݟͮΒ͍ • ೉ಡԽ࣌ʹੜ੒͞ΕΔmapping.txtΛ
 Google Play Console ʹΞοϓϩʔυ͠Α͏

  47. OS,୺຤ฤ

  48. OS, ୺຤ฤ • ػछґଘɺόʔδϣϯґଘɺύʔϛογϣϯɺ λεΫΩϥʔͳͲͰ࠶ݱͮ͠Β͍ͳͲ༷ʑͳ ໰୊͕ɻ

  49. ػछґଘ͕ܹ͗͢͠ • ؤுΔɻ • ϋʔυ΢ΣΞʹؔ͢Δͱ͜Ζ͸ؾ߹ͱࠜੑ • ݕূηϯλʔͳͲʹߦ͚Δ৔߹͸ར༻͢Δ • ͳΔ΂͘ɺSupport Library͕͋ΔػೳΛ࢖͏

  50. ϥϯλΠϜύʔϛγϣϯͷରԠ • Android 6.0͔Βಋೖ͞ΕͨϥϯλΠϜύʔϛ γϣϯ • ΞϓϦͷΠϯετʔϧ࣌ʹ͢΂ͯΛڐՄ͢Δ ͷͰ͸ͳ͘ɺ࢖༻࣌ʹڐՄΛٻΊΔ • ಠ࣮ࣗ૷͸ΊΜͲ͏ͳͷͰɺ


    hotchemi/PermissionsDispatcherΛ࢖͏
  51. Google Play Consoleฤ

  52. Google Play Consoleฤ • Google Play͸ɺGoogle ͕ӡӦ͢ΔετΞ • Android͸Φʔϓϯͳࢢ৔ͳͷͰɺ
 ԿॲͰΞϓϦΛ഑෍ͯ͠΋ྑ͍

    • Amazon StoreɺauεϚύεɺϒϩά • Google Play Console ͸Playͷ؅ཧը໘
  53. Android৹͕ࠪͳ͍͔Βɺ΍Γ ͍ͨ์୊ͳΜͰ͠ΐ͏ʁ • ͍͍͑ɻݫ͘͠ͳ͖ͬͯ·ͨ͠ɻ • ඞͣσΟϕϩούʔϙϦγʔΛ֬ೝɻ࣌ʑม ߋ͞ΕΔͷͰ஫ҙ͕ඞཁɻ • ݸਓ৘ใ΍ػີ৘ใ •

    ऩӹԽͱ޿ࠂ • ൒೥લͷϙϦγʔมߋ͸େ͖ΊͩͬͨͷͰɺ ඞͣ֬ೝ
  54. σΟϕϩούʔϙϦγͷྫ • มߋͷྫ • ݸਓ৘ใ΍ػີ৘ใ Ϣʔβʔͷݸਓ৘ใ΍ػີ৘ใ ʢݸਓࣝผ৘ใɺࡒ຿৘ใɺࢧ෷͍৘ใɺೝূ৘ใɺ ి࿩ா΍࿈བྷઌͷσʔλɺϚΠΫ΍Χϝϥͷηϯαʔ σʔλɺ୺຤ͷػີ৘ใͳͲʣΛѻ͏ΞϓϦ͸ɺҎԼ ͷཁ݅Λຬͨ͢ඞཁ͕͋Γ·͢ɻ

    • ஫ҙ͢Δ఺ • ऩӹԽͱ޿ࠂɹ޿ࠂ͸ɺ޿ࠂΛ഑৴͢ΔΞϓϦ಺ʹͷ ΈදࣔͰ͖·͢ɻΞϓϦ಺ʹ഑৴͞ΕΔ޿ࠂ͸ɺΞϓ ϦͷҰ෦ͱΈͳ͞Ε·͢
  55. ͍ͭެ։͞ΕΔͷ͔஌Γ͍ͨ • ެ։ϘλϯΛԡ࣮ͯ͠ࡍʹ൓ө͞ΕΔͷ͸
 ̎ʙ̏࣌ؒޙɻ௨஌ͷઃఆΛ͍ΕΔ͔ • Google Play Console ΞϓϦΛ͍ΕΑ͏

  56. ͱ͸͍͑΋ͬͱެ։͞ΕΔ·Ͱ ૣ͘ͳΒͳ͍ͷʁ • ܦݧଇͰ͕͢ɺBetaެ։͍ͯ͠Δ৔߹͸ɺެ ։ϘλϯΛԡͯ͠10෼ఔ౓Ͱ൓ө͞ΕΔ͜ͱ ͕ଟ͍Ͱ͢

  57. ·ͱΊ • Android Studio…ૉఢͰ͢ • Build.gradleपΓΛௐ΂Δͱ։ൃָ͕ʹͳΔ • σόοάπʔϧ΋๛෋ʹͳ͖ͬͯͨ • Google

    Play Console͸࠷ۙػೳ͕૿͑ͨͷͰɺ֬ೝ • ୺຤ґଘ͸͕Μ͹Δ • ProGuard͸ఆظతʹ͔͚࣮ͯߦ͢Δͱ҆৺
  58. ࢀߟจݙ • εϥΠυʹϦϯΫΛઃఆ͠·ͨ͠ • ͦͷଞ • DroidKaigi/conference-app-2017 • JakeWharton/u2020 •

    Android Developers
  59. ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ