TestFlightで「テストするAppがありません」と表示される

App Store Connectで登録済のApple IDでサインインしているiPadでTestFlightを開くと、「テストするAppがありません」と表示されてしまいテスト用アプリをインストールできない状態でした。

設定から一旦サインアウトしてサインインしなおしてみても解決しません。

このiPadではAppleIDメール受信の設定をしていなかったので、AppleIDのメールを受信できるように設定し、App Store Connect→TestFlight→App Store Connect Usersから一旦削除・再登録して招待メールを再送信しなおしました。

届いた招待メールから「Views in TestFlight」をクリックすると、TestFlightアプリの設定が更新されたようで、無事テスト用アプリがインストールできるようになりました。

Android 5より下のバージョンでjava.lang.ClassNotFoundException: Didn’t find class “smart.location.admin.hogehoge.MyApplication” on pathのエラーが出る

Android5以上のスマホでは正常に立ち上がるのに、5より下のバージョン、(ここでは4.3を利用して試しています。)では

java.lang.RuntimeException: Unable to instantiate application smart.location.admin.hogehoge.MyApplication: java.lang.ClassNotFoundException: Didn't find class "smart.location.admin.hogehoge.MyApplication" on path

というエラーが一番最初のコード実行時に出て、立ち上がらなくなることがあります。

APIレベルでいうと19以下ということですね。

下記の、

64K を超えるメソッドを使用するアプリ向けに multidex を有効化する

https://developer.android.com/studio/build/multidex

というのが関係しているので、読んでみて、自分のソースコードに合うのをやってみてください。
私の場合は、gradleを変更し、MyApplication(最初に実行されるクラス)を下記のように変更したらできました。

public class MyApplication extends Application { ... }

上記を下記に変更↓

public class MyApplication extends MultiDexApplication { ... }

Git 自分のした変更の履歴だけ見る

書くまでもないことかもしれないけど、書かないときっと忘れるシリーズ。

自分がした変更で、

「あれ、あそこでどうやってああしたんだっけ?」

みたいなの見たいことありますよね?

2パターン紹介しておきます。

Githubで簡単に見る方法

①見たいレポジトリを選択する

②Contributers というところをクリック

③自分の名前の下のコミットの数のところをクリック
これは場所がわかりにくいと思うのでスクショ載せておきます。
下記の赤丸のところです。

②Gitコマンドで見る方法

上記のGithubで見る方法だと、ブランチごとでしか見れなかったりしますね…。

どこのブランチでした変更か覚えていない場合、探すのが大変です。

そんな時は、Gitコマンドでやっちゃいましょう!

git log –pretty=”%h – %s” –author=”akiko.goto”

これで、ずらずらと出てきてくれます。

ちなみに、今回は自分の名前で、ってことになってますが、もちろん

–author=”akiko.goto”

のauthorを変えれば、ほかの人の修正履歴が見れるってことです!

参考:Git の基本 – コミット履歴の閲覧


Android実機にデバッグ版がインストールできない JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Invalid escape sequence at line 1

今日は表題のエラーで5時間ぐらいを費やしました…。

王大人「死亡確認!!」

さて、不思議なことが起こりまして、とあるAndroidアプリを、Release版はインストールできるんですが、Debug版が実機でインストールできない。

上記のエラーが出るんですよね。

最初は、google-services.json関係のエラーかと思って、その辺をFirebaseからダウンロードしたりしてましたが、直りませんでした。

結局、ほかのアプリで実績のある、gradleのバージョンとgoogle-servicesのバージョンの組み合わせで試したところ、無事に解決…。

buildscript {
repositories {
jcenter()
google()
}
dependencies {

classpath 'com.android.tools.build:gradle:3.2.1' //これ
classpath 'com.google.gms:google-services:3.2.0' // これ

}
}
 


Vue.jsを使って、facebookの通知エリアみたいなものを作るサンプルコード

「facebookの通知エリアみたいなもの」と言われても漠然としていると思いますが表示でいうと次のようなものです。

文章で要件を書くと次の通りです。

  • アイコンの右肩or左肩に未読件数のバッジが付いている
  • アイコンにマウスオーバーで下にプルダウンで表示される
  • メッセージ内容は動的に変更できる
  • 一件一件選んで消せる
  • 消したものは、既読フラグをつけて、もう未読エリアに表示しない
  • 重要なメッセージは色を変更するなどでわかりやすくする

私の javascript に関する能力としては、Web関係の仕事を5.6年前までは結構一生懸命やっていたけれども、javascriptは結局必要に迫られたときにjQueryとか jQuery UIとかでなんとかしていて、そんなに深くはやっていない、という感じのスキルです。

今回は、ちょっと急ぎで上記のものを作らないといけなくって、

「はは!この秀吉が、一夜で城を建ててみまする!」

という感じで、サクッとやる感じでやりました。結局4日間ぐらいはかかりましたので、4日城ですね。

使っているのは

  • Vue.js
  • Vuetify.js(バッジのデザインをこれにしたかった)
  • Semantic UI (メッセージのデザインをこれにしたかった)
  • axios(閉じるボタンをクリックした時に何か実行するため)

びみょいところもありますが、載せちゃいます。

<!DOCTYPE html>
<html>
<head>
<link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css"
	rel="stylesheet">
<link rel="stylesheet"
	href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css">

</head>
<body>
	<br>
	<div id="app">
		<div class="ui button"
			style="background-color: #ffffff; margin-left: 100px;">
			<!-- メールのアイコン -->
			<v-app style="height:50px; background-color:#ffffff;"> 
				<v-layout /> 
					<a>
						<v-badge color="red"  left> 
							<template v-slot:badge> 
								<span v-if="messages > 0">{{ messages }}</span>
							</template> 
							<bell v-on:showmenu="showMenuBelowBell()"
							v-on:hidemenu="hideMenuBelowBell()">
							</bell>
						</v-badge>					
					</a>
				</v-layout>
			</v-app>

			<!-- 通知 -->
			<notification v-for="post in posts" v-bind:key="post.id"
				v-bind:title="post.title" v-bind:content="post.content"
				v-bind:type="post.type" v-if="show_messages"></notification>
		</div>
	</div>

	<!-- 通知部分のテンプレート -->
	<script type="text/x-template" id="notification-component">
	  <div class="ui message" :class="type" v-if="!hidden" style="width:300px; text-align:left">	  
		<i class="close icon" @click="hide"></i>
		<div class="header">{{ title }}</div>
		<slot></slot>
		<div v-html="content"></div>
   	  </div>
	</script>

	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	<script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js"></script>
	<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

	<script>

	  Vue.component('bell', ({
			  template: '<span><i class="bell icon" v-on:mouseover="mouseover" ></i></span>',
	     	  methods: {
	  		    mouseover: function(){
	  		      console.log("マウスオーバーだよ");
		  		  this.$emit('showmenu') 
	  		    },
	
	  		    mouseleave:function(){
	  			  console.log("マウスリーブだよ");
	  			  this.$emit('hidemenu')
	  			},
	  		  }
		  	      
		}))	
			
  
	  Vue.component('notification', {
		  props: {
			  		title:{}, 
			  	  	content:{},
			        type: {
			            type: String,
			            default: 'info'
			         },
			        header: {
			       }
		  },
	      data() {
		        return {
		          hidden: false,
		   		 
		        }
		  },
	      methods: {
	          hide() {
	            this.hidden = true
	            axios.get(`https://api.github.com/users/AkikoGoto`)
	            .then(response => {
	              console.log(response.data)
	            })
	          },
	
	      },
		  template: '#notification-component'
		})	
		
		
		
	    
	  new Vue({
		  el: '#app',
		  vuetify: new Vuetify(),
		  data () {
		    return {
		     // show: false,
	
	 	      posts: [
	  		      { id: 1, title: 'せやかて' , content:'工藤', type:'info'},
	  		      { id: 2, title: 'なんだと' , content:'服部!本当なのか?', type:'error'},
	  		      { id: 3, title: 'お知らせ' , content:'ついに黒の組織のボスが判明'}
	  		    ],
	
	  		 messages: 3,
	  		 show_messages:false,
	
		    }
		  },
	
		  methods: {
	
			  showMenuBelowBell: function () {
			      this.show_messages = true
	
			    },
	
			  hideMenuBelowBell: function () {
				  this.show_messages = false
	
			    }		    		    
			    
			  }
	
		})
	
  </script>
</body>
</html>

一応、これを張り付けてhtmlファイルとしてブラウザで開けば、一番最初の画像のような挙動になるはずです。

注意点は次の通り。

  • データはVueを生成しているところ(new Vueの箇所)のpostsというところに入っています。JSONだとかなんらかの形で、ここが動的に変わるようにしてください。
  • バッジの件数は、その下のmessagesというオブジェクトになります。すみませんが、上記のpostsを自動的にカウントして入れるようになっていませんので、ここも別途やってくださいませ。
  • 閉じる×ボタンをクリックした時の挙動は、私のGithubにつながって応答が返ってきてconsoleに出力されるようになってます…。もちろん、ここも皆様がカスタマイズされると思いますので、ただのサンプルです。
  • プルダウンメニューが表示されるところはやってありますが、全体的に隠す処理はしていません。そちらもご自由に…。