2018年5月1日火曜日

[Tennis]東京都稲城市周辺の硬式テニスのガットを張ってくれるお店情報

購入ガット持ち込みガット最終確認日備考
カムイ若葉台店100030002018/5店頭に無いガットも注文すれば入手可能な場合あり(Yonexマルチセンサ125を注文しました)
テニスサポートセンター(仙川店)2376?2018/5
ラケットショップフジ132013202021/12川崎駅周辺
持ち込みガットの場合張り上げまで時間がかかるときあり(2-3日)
橋本駅周辺にもお店あり
テニスショップウェイ新百合ヶ丘110022002021/12
ウィンザーテニスショップ聖蹟桜ヶ丘209023902021/12
Let's Tennis School162021602018
Sports Authority86421602018/6
スポーツデポ ぐりーんうぉーく多摩店
フジスポーツ 本店(武蔵小杉)90020522018/5
ラック 溝ノ口店
パパステニスクラブ津久井22002021/12
税込み

2018年2月11日日曜日

[Android]LINEアプリでOS設定のアプリ権限で「位置情報」をOFFにすると動作が遅い

[2018/06/30] この時点の版から位置情報をOFFにしても動作に不具合がなくなりました。

いつからかAndroid上のLINEアプリケーションの動作がおかしくなりました。

例えば:

  1. ボタン部分を押しても押したことを一回無視される。
  2. IMEを有効にしてHOMEボタンを押してLINEを一度back groundに移動して、再度LINEを起動すると、IMEの表示→非表示まで時間がかかる。
その後手元の端末だけの問題と分かりlogcatでエラーが出ていないか調べてみました。

以下の通り、BLEの処理をしているけど、PERMISSIONが無いためexceptionが出ていました。

そこで、OS設定のアプリ権限でLINEの「位置情報」を「ON」に変更したところ改善しました。個人的には不要なパーミッションはOFFにしたいので、改善して欲しいところです。

環境
Android 8.1
LINE 8.1.1

問題発生時のlogcat


02-10 17:11:09.157 2124-2124/? I/GoogleInputMethod: onFinishInput() : Dummy InputConnection bound
02-10 17:11:09.157 2124-2124/? I/GoogleInputMethod: onStartInput() : Dummy InputConnection bound
02-10 17:11:09.161 883-944/? I/ActivityManager: Displayed jp.naver.line.android/.activity.chathistory.ChatHistoryActivity: +194ms (total +254ms)
02-10 17:11:09.185 2124-2124/? I/GoogleInputMethod: onFinishInput() : Dummy InputConnection bound
02-10 17:11:09.224 3181-3181/? V/View: dispatchProvideAutofillStructure(): not laid out, ignoring 0 children of 1073741840
02-10 17:11:09.224 3181-3181/? V/View: dispatchProvideAutofillStructure(): not laid out, ignoring 1 children of 1073741843
02-10 17:11:09.225 3181-3181/? V/View: dispatchProvideAutofillStructure(): not laid out, ignoring 0 children of 1073741853
02-10 17:11:09.225 3181-3181/? V/View: dispatchProvideAutofillStructure(): not laid out, ignoring 3 children of 1073741862
02-10 17:11:09.226 3181-3181/? V/View: dispatchProvideAutofillStructure(): not laid out, ignoring 4 children of 1073741874
02-10 17:11:09.226 3181-3181/? V/View: dispatchProvideAutofillStructure(): not laid out, ignoring 4 children of 1073741875
02-10 17:11:09.228 883-22436/? W/Binder: Outgoing transactions from this process must be FLAG_ONEWAY
                                         java.lang.Throwable
                                             at android.os.BinderProxy.transact(Binder.java:752)
                                             at android.app.assist.AssistStructure$ParcelTransferReader.fetchData(AssistStructure.java:407)
                                             at android.app.assist.AssistStructure$ParcelTransferReader.go(AssistStructure.java:343)
                                             at android.app.assist.AssistStructure.ensureData(AssistStructure.java:2100)
                                             at com.android.server.autofill.Session$1.send(Session.java:227)
                                             at com.android.server.am.ActivityManagerService.reportAssistContextExtras(ActivityManagerService.java:13272)
                                             at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:2472)
                                             at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2919)
                                             at android.os.Binder.execTransact(Binder.java:697)
02-10 17:11:09.229 3181-3181/? I/AssistStructure: Flattened final assist data: 12784 bytes, containing 1 windows, 56 views
02-10 17:11:09.250 883-2370/? I/AssistStructure: Flattened final assist data: 12672 bytes, containing 1 windows, 56 views
02-10 17:11:09.463 698-698/? D/QCOM PowerHAL: LAUNCH HINT: OFF
02-10 17:11:09.799 3181-3219/? E/System: Ignoring attempt to set property "java.net.preferIPv6Addresses" to value "false".

2018年1月21日日曜日

[Google Assistant, IFTTT] Google Homeに話しかけてhttp://diet.dyndns.orgの体重グラフを自動Update


Google Home/Assistantに話しかけて体重グラフを自動で更新する方法

[2018/1/24] 体重にいわゆる半角全角が混ざっている場合にうまく半角に出来ない問題があります。近日修正予定です。
[2018/1/25] 半角全角が混ざるのではなく、61.2kgといったときに "6[半角スペース]1.2kg"という文字送られてきているのが問題でした。スペースを削除するようにしました。
[2018/2/18] IFTTTの返事文言を変更しました。
[2018/2/21]体重グラフのWebページがhttps化されたため。Google App Scriptを変更しました(http→https)。
[2018/3/16] Amazon Alexa用のskillを作成し、現在Amazonの審査中です。公開でき次第こちらにも記載します。また時間がとれればGoogle Assistant用のアプリも作成できればと思います(機能は本IFTTT版とほぼ同じです)
[2018/3/23] Amazon Alexa用skillとして、「体重グラフ」を公開しました。ご要望があれば、weight-graph at sanpei.org にメールください。Google Assistant用のアクション(アプリ)も作成予定です。
[2018/3/25] Google Assistant(Google Home)用のアクションとして「体重グラフ」をGoogleに公開申請しました。公開できましたらこちらに記載します。
[2018/3/27] Google Assistant(Google Home)用のアクションとして「体重グラフ」をGoogleに公開しました。そのため以下の内容は技術的な参考として引き続き掲載します。

各スキル・アクションのコードは以下のgithubで公開中です。

Amazon Alexa用skill code

Google Assistant用Action code



以下の設定の説明します。

1) IFTTTの設定
2) Google App Scriptの説明

1) IFTTTの設定


1-1) IFTTTの設定のポイント
1-1-1) IFの"Say a phrase with a text ingredient"の利用
当初は体重は数字なので"Say a phrase with a number"を使っていましたが、Google Assistantが体重部分をいわゆる全角で認識する場合があり、そうすると数字ではなく文字列になりました。そのため、現在は"Say a phrase with a text ingredient"を利用しています。
1-1-2) Languageは日本語(Japanese)に変更しています。

2) Google App Script

2-1) Google App ScriptはIFTTTと連携するGoogle DriveのGoogle Sheetで[Tools]->[Script editor...]で開いて入力ください(本例では、"IFTTT/sanpeiweight"の"Google Assistant Commands")

2-2) Google App Scriptの操作方法はこちらのYouTubeが参考になりました。
[Resources] -> [All your trigger]か以下のボタンからTrigger追加してください。

2-3) diet.dyndns.orgのユーザー名とパスワードは、Google Sheetのシート名[Auth]のB1セルにユーザー名、B2セルにパスワードを入力してください。

2-4) 簡単な各関数の説明
関数addDate:
A) IFTTTでThen "Add row to spreadsheet"でなぜか"Add row to spreadsheet"をしても正しくCreatedAtが入らないためGAS側でA列に日付を入れています。
B) Google Assistantが時々いわゆる全角文字で体重を認識するため全角を半角に変換しています。-->[2018/1/25] 全角ではなく、数字の途中に不要なスペースが入る場合がありその削除対応をしています。
C) updateDietの呼び出し

関数updateDiet:
A) Diet.dyndns.orgと通信しながら、現在の時刻で体重を記録します。


function addDate(e) { 
  var authSheetName = "Auth";
  var activeSheet = SpreadsheetApp.getActiveSheet();
  if (activeSheet.getName() != authSheetName) {
    var lr = activeSheet.getLastRow(); 
    var weight = activeSheet.getRange(lr,2).getValue().toString();
    weight = zenToHan(weight);
    activeSheet.getRange(lr, 2).setValue(weight);
    var CurrentDateString = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "MMM d yyyy HH:mm:ss");
    activeSheet.getRange(lr, 1).setValue(CurrentDateString);
    
    updateDiet(weight, authSheetName);
  }
}

function updateDiet(weight, authSheetName) {
  var bk = SpreadsheetApp.getActiveSpreadsheet();
  var authSheet = bk.getSheetByName(authSheetName);
  var userId = authSheet.getRange(1,2).getValue().toString();
  var password = authSheet.getRange(2,2).getValue().toString();
  
  // 1. open login page
  var LOGIN_URL = "https://diet.dyndns.org/?cmd=login&user="+userId+"&password="+password
  var response = UrlFetchApp.fetch(LOGIN_URL, {'followRedirects': false, 'muteHttpExceptions': false});
  Utilities.sleep(1000);

  var headers = response.getAllHeaders();
  var cookies = [];
  if ( typeof headers['Set-Cookie'] !== 'undefined' ) {
    // Set-Cookieヘッダーが2つ以上の場合はheaders['Set-Cookie']の中身は配列
    cookies = typeof headers['Set-Cookie'] == 'string' ? [ headers['Set-Cookie'] ] : headers['Set-Cookie'];
    for (var i = 0; i < cookies.length; i++) {
      // Set-Cookieヘッダーからname=valueだけ取り出し、セミコロン以降の属性は除外する
      cookies[i] = cookies[i].split( ';' )[0];
    };
  }
  
  // 2. open redirect page
  REDIRECT_URL = "https://diet.dyndns.org/?cmd=user&";
  var options = {
    method : "POST",
    contentType: "application/x-www-form-urlencoded",
    headers: {
      Cookie: cookies.join(';')
    },
  };
  response = UrlFetchApp.fetch(REDIRECT_URL, options);
  Utilities.sleep(1000);
  
  // 3. set weight
  WRITE_URL = "https://diet.dyndns.org/";
  var date = new Date();
  var timeZone = Session.getScriptTimeZone();
  var year = Utilities.formatDate(date, timeZone, "y");
  var month = Utilities.formatDate(date, timeZone, "M");
  var day = Utilities.formatDate(date, timeZone, "d");
  var hour = Utilities.formatDate(date, timeZone, "H");
  weight = weight.toString();
  var options = {
    method : "POST",
    contentType: "application/x-www-form-urlencoded",
    headers: {
      Cookie: cookies.join(';')
    },
    payload : {
      year: year,
      month:month,
      day:day,
      hour:hour,
      weight:weight,
      comment:"",
      cmd:"user",
      mode:"input"
    }
  };
  response = UrlFetchApp.fetch(WRITE_URL, options);
}

function zenToHan(s) {
  s = s.replace(/[0-9.]/g, function(s) {
      return String.fromCharCode(s.charCodeAt(0) - 65248);
  });
  return s.replace(/ /g, "");
}


ちなみに、バックアップも兼ねて以下のようにGoogle SheetにもA列に日時、B列に体重が入ります。