Androidアプリ開発 メモリの消費をなるべく抑える

Android

Androidアプリ開発 メモリの消費をなるべく抑える

私のようなサーバーサイドプログラムからスマホアプリ開発に移行してきたプログラマにとっては、スマホのメモリが少なすぎて、いろんな処理ができないのはとても悲しく感じますが、しかしやらねばならぬときもありますね。
アプリがメモリ消費が少なければ少ないほど、そのアプリは早く動くからです。

ちょっと盲点だったことに、下記のブログが言及していたので、メモしておきます。

Avoiding memory leaks
http://android-developers.blogspot.jp/2009/01/avoiding-memory-leaks.html

Romain Guyさんという人が2009年にいわく、メモリーリークの原因の多くは、Contextのむやみな使いまわしにある、ということです。

あー、あるある。ありますよ!

とにかく使うContext。

 //Activity内
 Context context = this;

上記のようにContext = Activity として、いろんなところで使いまわしていませんか?
私は、結構してました。orz

つまり、ContextがActivityなわけだから、Contextを渡しちゃうと、Activity全体への参照がいつまでたっても残ってしまい、メモリーを使い続けちゃうってわけなんですね。

でも、Contextが必要なんだよぉぉ という人は、

 Context.getApplicationContext() or Activity.getApplication().

を使いたまえ、ということだそうです。

にゃるほど!!

他にもブログのサンプルコードには、下記のようなことはダメ!絶対!ということです。
まー、こんなことする人いるのかな?
と思いますが、ありえない話ではないですよね。

 private static Drawable sBackground;
 
 @Override
 protected void onCreate(Bundle state) {
  super.onCreate(state);
  
  TextView label = new TextView(this);
  label.setText("Leaks are bad");
  
  if (sBackground == null) {
    sBackground = getDrawable(R.drawable.large_bitmap);
  }
  label.setBackgroundDrawable(sBackground);
  
  setContentView(label);
 }

そのライフサイクルをコントロールできないstaticではないインナークラスを使わないこと、だそうです。
WeakReference を使った、staticなインナークラスを作りましょうね!というこどです。

Androidアプリの月額課金の方法!

Android

Androidアプリでの月額課金の方法をまとめました!

&size(24){&color(red){まとめ};なので、さくっと進めます!};

まず、Google Play Developerにアカウントを取得します!
その後、Google Wallet merchant のアカウントを取得します!
これで準備ができました。

必要なものリスト

  • In-app Billing API
  • Android 2.2以上
  • Play Store 3.5以上
  • SDK

価格設定について

  • Googleウォレットマーチャントアカウントに、注文、払い戻し、履歴のレポートが見れる
  • 0円は指定不可
  • 月額、年額
  • 試験させることができる
  • 現在は定期購入の価格は変更できない

定期購読の試用期間が設定できます

7日間から設定できます!

サービスIDについて

  • 同じアプリ内でのIDの重複は禁止
  • 小文字、数字、アンダーバー、ドットのみ使用可能
  • 変更不可
  • 再利用不可

現時点での月額課金設定でできないことがあります・・・

  • 価格変更
  • 非公開
  • サービスIDの変更、再利用
  • 購読ユーザーが存在するアプリの削除

ようやく手順の秘密を伝授しましょう・・・

1.Google Play デベロッパー コンソールにログインします。
2.左側のナビゲーション バーで [すべてのアプリケーション] をクリックしてアプリを選択します。
3.[新しいサービスを追加] をクリックします。
4.[定期購入] を選択します。
5.[アプリ内サービス ID] を追加して [次へ] をクリックします。
6.必要なパラメータを追加します。
7.[保存] をクリックします。
8.APKマニフェストファイルに、com.android.vending.BILLING の権限を宣言する
9.50行程度の必要なコードを書きましょう!!(昔は250行もあった!)

ちなみに…

手数料は30%です。

Android リリースしたアプリの月額課金をテストする

  • 月額課金にする場合、アプリ自体の価格は無料に設定しますか?それとも月額課金と同金額で設定するのでしょうか?よろしくお願いいたします。 — 悩める人 {2017-05-02 (火) 21:14:07}

Androidアプリのパッケージ名を最速で変更

Android

Androidアプリを開発している時、稀に出てくるのがパッケージ名を変えるという問題です。
こんな作業している暇があったら素晴らしいアプリの開発に専念していただきたいものです。
そこで、最速でパッケージ名を変える方法を編み出しました!
(筆者は2回もパッケージ名を変えた経験があります。)

AndroidManifest.xmlのパッケージ名を修正

マニフェストファイルの変更する部分は以下です。

 <manifest
    package="パッケージ名">

srcがたくさんエラーが出ますが、私はそんなことに構ってられるほど小さい男ではありません。
「Package Explorer」の「gen」を見ると、新しいパッケージ名が表示されているはずです。

srcのパッケージ部分を変更したいパッケージ名に変更

「Package Explorer」のsrc以下にあるパッケージ名を変更しましょう。
パッケージを右クリックし、「Refactor」→「Rename」で変更することができます。
メインとなるパッケージ以外にもサブのパッケージがある場合は、「Rename subpackages」にもチェックを入れましょう。
大事の前の小事っていいますね!

gen以下の古いパッケージを削除しましょう

これでパッケージ名を変更することができましたね。

猿「非常に簡単でした。私でもできましたから。」

Androidアプリからnode.jsに接続するとFile Not Found Exception

Java
Android
node.js
Express

ちょっと解決まで時間がかかったので書いておきます。
Expressは最近触り始めたのであまり知識がありません。

Androidアプリから、node.js + expressのサーバーに通信して、結果を取得するAPIを作成していました。
が、AndroidアプリでURLに接続すると

 File Not Found Exception 

で接続できない。
ブラウザでは普通に接続できるんですけど。
Javaではあるある~ ですよね。
サーバーからは404が帰ってきます。

で、最初はexpressの方かな?と思いまして、下記のようにわざわざ

 res.status(200)

をつけてみました。

 router.get('/route_out', function(req, res, next) {
 	console.log("route_out");
 
  res.status(200).send('broadcasted');
 
 });

ですが、

 File Not Found Exception 

は依然としてそのまま…。

node.jsを走らせていると、コンソールに次のような表示が…。

 POST /broadcast/route_out 404 35.966 ms - 947

あれっ アプリからはGETではなくて、POSTで接続してるじゃん!
とアプリのコードをよく読むと

 @Override
 protected String doInBackground(String... params) {
 
 	String string = null;
 	HttpURLConnection urlConnection = null;
 

try {

 			
 		URL url = new URL(params[0]);
 		   
 		urlConnection = (HttpURLConnection) url.openConnection();
 	    	urlConnection.setDoOutput(true);
 	    	urlConnection.setChunkedStreamingMode(0);
 
 	    	InputStream in;
 		    
       		int status = urlConnection.getResponseCode();
 
                if (status != HttpURLConnection.HTTP_OK){
 		            
 	            	in = urlConnection.getErrorStream();
 	            	Log.e(TAG, "サーバーからのレスポンスエラー " + status);
 	            
 	            }else{
 		 
 	            	in = new BufferedInputStream(urlConnection.getInputStream());
        		string =convertInputStreamToString(in);
 		    	Log.d(TAG, string);
 		    		    
 	            }
                
 		} catch (IOException e) {
 			// TODO Auto-generated catch block
 			e.printStackTrace();
 		}finally {
 		    urlConnection.disconnect();
 		}
 
 		return string;
 }

となっていて、

 urlConnection.setDoOutput(true);
 urlConnection.setChunkedStreamingMode(0);

この二つがいらなかったですね(;^ω^)

この二つを消して、下記を加えたら解決しました!

 urlConnection.setRequestMethod("GET");

Androidのディスプレイサイズがxhdpiなのかxxhdpiなのか

Android

Androidのディスプレイサイズがxhdpiなのかxxhdpiなのか

Androidアプリを作っていて、とてもめんどくさいのが多種なスクリーンサイズに対応することですね。

「あれ、この端末で見た目がおかしいよ?」という時、まずはその端末が下記のどの画面サイズのグループに該当するのか確かめるのが先です。

mdpi:160dpi
hdpi:240dpi
xhdpi:320dpi (Galaxy S3a)
xxhdpi:480dpi (HTC J butterfly)
xxxhdpi : 640dpi

というわけで、上記の画面密度グループを表示するサンプルコードです。

 WindowManager windowManager = getWindowManager();
 Display display = windowManager.getDefaultDisplay();
 DisplayMetrics displayMetrics = new DisplayMetrics();
 display.getMetrics(displayMetrics);
 Log.d(TAG, "ディスプレイの密度グループ"+displayMetrics.densityDpi);

HTC J butterflyって乃木坂46がCMしているんですね!(・∀・)