フリーランス 技術調査ブログ

フリーランス/エンジニア Ruby Python Nodejs Vuejs React Dockerなどの調査技術調査の備忘録

android スプラッシュからの携帯電話情報の取得

はじめに

  • androidでスプラッシュ画面から遷移して携帯電話情報を取得して画面表示するサンプルを作ってみた

manifestファイル

  • 携帯電話情報を取得するために下記のXMLを記述する
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />

app\build.gradleファイル

  • コルーチンを利用するためにkotlinxをインポートする。スプラッシュからトップ画面に遷移するために利用する
plugins {
    id 'com.android.application'
    id 'kotlin-android'
    //以下1行追加
    id 'kotlin-android-extensions'
}

dependencies {
   (省略)
   implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.1'
}

スプラッシュ画面

  • スプラッシュのactivityのコード。2秒後にトップ画面に遷移する
class SplashActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash)

        val ivSplash = findViewById<ImageView>(R.id.ivSplash)
        val assets = resources.assets
        try {
            assets.open("splash.jpg").use { istream ->
                val bitmap = BitmapFactory.decodeStream(istream)
                ivSplash.setImageBitmap(bitmap)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        CoroutineScope(Dispatchers.Main).launch {
            delay(2000)
            val intent = Intent(this@SplashActivity, MainActivity::class.java)
            startActivity(intent)
            finish()
        }

    }
    
}

f:id:PX-WING:20210716080356p:plain

トップ画面

  • 携帯電話情報の権限を確認して許可を得たら携帯電話番号を表示する処理をする
  • アンドロイドのバージョンによって携帯電話番号取得の権限が異なるのでバージョンごとに権限の値を切り替え。 Build.VERSION.SDK_INTを利用してバージョンを切り替える
private const val REQUEST_PHONE_PERMISSION = 200

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        getPhoneNumber()
        var wevview = findViewById<WebView>(R.id.topWebview)
        wevview.loadUrl("https://www.google.co.jp/")
    }

    private fun permissionPhoneCheck(): Boolean {
        // ToDo: https://developer.android.com/about/versions/11/privacy/permissions?hl=ja
        var phonePermission: String = Manifest.permission.READ_PHONE_STATE
        if(Build.VERSION.SDK_INT >= 30){
            phonePermission = Manifest.permission.READ_PHONE_NUMBERS
        }
        var permissions: Array<String> = arrayOf(phonePermission)
        // 権限のチェック
        if (ActivityCompat.checkSelfPermission(this@MainActivity,
                phonePermission) != PackageManager.PERMISSION_GRANTED) {
            // 権限がないため、権限のリクエスト
            ActivityCompat.requestPermissions(this@MainActivity,
                permissions, REQUEST_PHONE_PERMISSION)
            return false
        }
        return true
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String?>,
                                            grantResults: IntArray) {
        when (requestCode) {
            REQUEST_PHONE_PERMISSION -> {
                if (grantResults.isNotEmpty() && grantResults[0] ==
                    PackageManager.PERMISSION_GRANTED) {
                    getPhoneNumber()
                    Toast.makeText(this, "電話の発信と管理の許可を設定しました", Toast.LENGTH_SHORT).show()
                } else {
                    Toast.makeText(this, "電話の発信と管理の許可がありません.", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }

    private fun getPhoneNumber(): String {
        val telnumber = findViewById<TextView>(R.id.txTelnumber)
        if (permissionPhoneCheck()) {
            val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
            telnumber.text = telephonyManager.getLine1Number().toString()
            return telephonyManager.getLine1Number().toString()
        } else {
            telnumber.text = "(電話番号は取得できませんでした)"
            return "(電話番号は取得できませんでした)"
        }
    }

    fun onButtonClick(view: View) {
        var phoneNumberTxt: String = getPhoneNumber()
        val dialog = AlertDialog.Builder(this)
            .setTitle("あなたの携帯電話番号は")
            .setMessage(phoneNumberTxt)
            .setPositiveButton("OK") { dialog, which ->
                Toast.makeText(this, "OKがタップされた", Toast.LENGTH_SHORT).show()
            }
            .create()
        dialog.show()
    }

}

f:id:PX-WING:20210716080418p:plain

f:id:PX-WING:20210716080522p:plain

Windows/Docker上でswiftを動かす

環境構築

1 . Windows10PCにDockerデスクトップをインストールします

  1. swift.orgからSwiftdockerイメージを取得します swift.org

swiftのイメージをPullしてくる

docker pull swift

下記のようにswift dockerを起動してswiftコマンドを実行するとエラーが発生する

docker run -it swift /bin/bash

# swfit
error: failed to launch REPL process: process launch failed: 'A' packet returned an error: 8

swift docker環境を起動

  • 下記のように指定して起動する。
docker run --privileged -v C:\Users\hogehoge\swfit_workspace:/app -it --rm --name swift-latest swift:latest /bin/bash

Dockerコンテナ内の実行

cd app (Windows環境のフォルダをマウントしている箇所)
mkdir example
cd example
swift package init --type executable
  • Swiftを実行する
swift run

実行結果

swift run
[3/3] Build complete!
Hello, world!

OpenProjectをインストールして個人開発のスケジュールを管理する

OpenProjectのインストール

  • 下記の手順でローカルでOpenProjectを動作できる環境を構築することができる
git clone https://github.com/opf/openproject-deploy --depth=1 --branch=stable/11 openproject
cd openproject/compose
docker-compose pull
http://localhost:8080/

ブラウザをアクセスするとログインIDとPWを求められるのでIDとPWに「admin」を入れてログインする。

日本語の設定

  • 画面右上のユーザーアイコンをクリックして[Administration]-[System settings]-[Display]タグを選択し[日本語]にチェックを入れる。

ガントチャート

  • 結構きれいに表示され、操作性も問題なし f:id:PX-WING:20210614231706p:plain

バックログ機能

  • 一人で開発するのであれば十分な機能 f:id:PX-WING:20210614231825p:plain

WordPressのバージョンアップ依頼や引継ぎ依頼がきた場合の確認項目を検討してみた。

はじめに

  • WordPressのバージョンアップや、運用している人がいなくなったので引き継いでほしいという話はよくあるが、自分がもしその案件を受けるなら下記の事前ヒアリングをしてボリューム感をヒアリングしてから概々算見積を出す。詳細見積を出す人の勇気が凄い。

現在の開発サーバーの環境構築について教えてください

確認項目 確認理由
利用しているクラウドサービス(AWS or GMOなど)且つ契約しているプラン(GMOなどのサービス) PHPのーバージョンができるか確認するため、契約次第では、サーバーを引っ越す必要があるため。
ミドルウェアのバージョン
- OS / Webサーバー(apache/nginxなど)/ DB(mysqlなど)のバージョン
- メールサーバーの利用
- DNSサーバーの確認(お名前.comなど)
- 利用しているSSLの確認
外部から確認できるので、ヒアリングしなくてもよいか自分の調べた情報に確証をもつためにもヒアリングまたはサーバーの接続情報をもらう
アクセス制限などかかっているか確認 作業を行う場合、特定の場所しか作業できない場合、出向く費用などが発生するので確認が必要
ファイルのバージョン管理をしている(Githubなど) WordPressで運用しているサイトは、比較的にバージョン管理していないのがおおい。(個人の感想です)
外部サービス(APIなど)を利用しておりますでしょうか。 GMOや外部APIサーバーと通信などしているか
現在サイト運用はどのような方法で運用されておりますでしょうか。 FTPサーバーなどでファイルをアップロードしているとか、ヒアリングは必要
現在利用しているWPのプラグインを教えてください。プラグインをカスタマイズしているでしょうか。 プラグインをカスタマイズするケースはよくある。そのプラグインをバージョンアップする場合、現行仕様を調査しないといけないため、結構時間取られるポイント。代替えのプラグインなども提案しないといけないケースがあるため。
開発環境用サーバーはありますでしょうか。 バージョンアップするための検証環境がない場合、開発環境の構築から必要なため。
サービス停止の可否を確認する バージョンアップ時にはサーバーを停止させることがしばしばあるが、停止NGの場合、方法を検討しないといけないため。
バージョンアップ予算 先方の予算を確認する
バージョンアップ期限 先方のバージョンアップしたいデッドラインの日程。よくあるのはサーバーの契約があと〇日で切れるからなるはやで。

調査環境の構築

  • もし上記のヒアリングを行い、順調に案件が進んだらdocker環境で先方の環境の構築と最新のWordPressの環境を構築して移行する際にどのような障害が発生するか事前に確認しましょう。※ここまで調べて失注したらどうしようと悩むより受けた後に膨大な赤字を出すよりもましだ。

docs.docker.jp

※Docker最強!!

pythonでサイト内の画像をダウンロードと画像圧縮

はじめに

  • サイト内に取得する画像のリストをCSVで事前に用意しておく。
filename
http://www.example.com/images/hoge600444hgea0a9dad15a.png
http://www.example.com/images/hoge600a22222hoge30.png
http://www.example.com/images/hoge6dsa33300a0ae73178e.png

パッケージインストール

pip install Pillow

docs.python.org

コード

import urllib.error
import urllib.request
import glob
from PIL import Image

# 指定したURLの画像を指定したフォルダへ保存する処理
def download_image_file(url, save_path):
    try:
        with urllib.request.urlopen(url) as web_image_file:
            data = web_image_file.read()
            with open(save_path, mode='wb') as local_image_file:
                local_image_file.write(data)
    except urllib.error.URLError as e:
        print(e)

def download(request):
    path = '/<CSVファイルのパスを指定>/images.csv'
    with open(path) as f:
        for url in f:
            url = url.rstrip()  
            file_name = url.split('/')[5] # ファイル名のみ取得。URLの階層次第で数値の指定が異なる
            dst_path = 'data/' + file_name
            download_image_file(url, dst_path)

 # ダウンロードした画像を圧縮してrenameして保存する処理
    files = glob.glob("data/*")
    for file in files:
        image = Image.open(file)
        resize_img = image.resize(image.size, Image.LANCZOS) 
        resize_img.save(file.replace('/', '/resize-'))

django/pandasでCSVファイルを結合する

インストール

  • django-pandasというパッケージもあるが普通にpandasをインストールして使う。
pip install pandas

CSVファイルのサンプル

  • 下記の2つのCSVファイルをfilenameをキーに結合する
itemid itemname filename
4 商品1 hoge600444hgea0a9dad15a.png
5 商品2 hoge600a22222hoge30.png
6 商品3 hoge6dsa33300a0ae73178e.png
filename size
hoge600444hgea0a9dad15a.png 111282
hoge600a22222hoge30.png 69672
hoge6dsa33300a0ae73178e.png 95212

サンプルコード

  • encoding="cp932"を指定することでCSVファイルが日本語入っていても文字化けしない
  • on="filename"で結合するためのキーを指定する
  • to_csvメソッドで結合したファイルを出力する
from django.shortcuts import render
import pandas as pd

def index(request):
    item_list = pd.read_csv('/code/demo/scraping/item_list.csv',encoding="cp932")
    item_image_list = pd.read_csv('/code/demo/scraping/item_image_list.csv',encoding="cp932")
    items = pd.merge(item_list, item_image_list, on="filename")
    items.to_csv("items.csv", encoding="cp932")

Windows環境でWSL2/UbuntuとDockerをインストールする

前回の続き

- WindowsにWSLをインストールまでしたので、WindowsLinuxをインストールしてみる px-wing.hatenablog.com

手順

Linuxディストリビューションをインストールします

f:id:PX-WING:20210519081504p:plain

f:id:PX-WING:20210519081930p:plain

  • インストール後、ubuntuが起動されてuser名とパスワードを入力して利用できるようになる f:id:PX-WING:20210519083458p:plain

  • インストールされたubuntsのバージョンを確認するため、ターミナル上でcat /etc/os-releaseを実行する

$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.2 LTS (Focal Fossa)"
  • Powershellを管理者モードで起動しwsl -l -vを実行すると、ubuntsがwsl2で設定されていることを確認できる
PS C:\Windows\system32> wsl -l -v
  NAME      STATE           VERSION
* Ubuntu    Running         2

Dokcerをインストールする

  • 下記のサイトからDockerのexeファイルをダウンロードする hub.docker.com

  • ダウンロードしたインストーラーを起動してインストールを行う。インストールする際は赤枠のチェックを外さない f:id:PX-WING:20210519090741p:plain

※ここまで作業すればDocker環境が構築できます。