2018年6月16日土曜日

[Android SDK] targetSdkVersion 26に変更したらRemoteViewsで例外が発生して対処

メモガキのtargetSdkVersionを24から26に変更する作業を進めていたら、ウィジェット設定画面でウィジェットのプレビューが表示され無い問題に気づきました。



となるところが、



上部のプレビューが消えてしまいました。
このウィジェットのプレビューは、AppWidgetHostViewを利用してActivity中にAppWidgetを表示するビューを作成しています。

Android StudioのLogcatを確認すると、
  1. android.widget.RemoteViews$ActionException: view: android.support.v7.widget.AppCompatImageView can't use method with RemoteViews: setImageBitmap(class android.graphics.Bitmap)  

と出力されているため、AppCompatImageViewがAppWidgetで使えないことが原因であることはすぐに気づきました。
どこかの処理で、ImageViewがAppCompatImageViewに置き換えられてしまったようです(レイアウトファイルは変更していないから)。

試行錯誤していたら、rv.applyに対してContextを指定している箇所を、Activity(AppCompatActivity)からApplicationContextに変更して解決しました。
  1. AppWidgetHostView hostView;  
  2. RemoteViews rv;  
  3. rv.apply(getApplicationContext(), mPreviewWidget);  
  4.   
  5. hostView.removeAllViews();  
  6. //View view = rv.apply(this, hostView);  
  7. View view = rv.apply(getApplicationContext(), hostView);  
  8. hostView.addView(view);  

targetSdkVersionを変えた際にsupport.v4のバージョンも変更したから、AppCompatActivityの挙動が変わったようですね。

2016年11月3日木曜日

[Android SDK] 画面の回転を固定にする

画面回転に対応したActivityを作成していた場合で、動的に回転を固定した場合には下記を実行することで固定できる。

■画面回転を固定にしたい場合
  1. getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);  

■画面回転の固定を解除したい場合
  1. getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);  

2015年6月10日水曜日

[メモガキ開発日記] 毎朝、今日のメモを表示する機能を作る

メモガキの新機能として、毎朝、今日のメモを確認できる機能を作ります。

使い道

通知機能(リマインダー)を使うことでもメモを見返せますが、朝に今日のメモをまとめて確認できるようにする。これだけでは、普通にメモガキを起動すれば確認できます。
そこで、メモガキを起動することを忘れたとしても、朝起きてスマホの画面をオンにするだけで、今日のメモが表示されるようにする。



作る

メモガキがスマホの画面がオンされたことを常時検知できる必要があるので、サービスを作成し、常時サービス内で画面オンイベントを受け取れるようにする。サービスが画面オンイベントを受け取ったら、今日のメモを表示するアクティビティを起動します。

全体像として、アクティビティ(Activity)、サービス(Service)、アンドロイド(Android)間の制御は次のように作成します。



①サービス起動、②サービス停止

サービスの起動・停止は、ContextのstartService、stopServiceメソッドを使います。
  1. Context context = getActivity().getApplicationContext();  
  2. Intent serviceIntent = new Intent(context, RpService.class);// サービスのクラスを指定  
  3.   
  4. // サービス起動  
  5. context.startService(serviceIntent);  
  6.   
  7. // サービス停止  
  8. context.stopService(serviceIntent);  


③画面オンの受け取り

画面オンイベントは、BroadcastReceiverを使うことでAndroidからイベントを受け取ることができます。
  1. BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {  
  2.     @Override  
  3.     public void onReceive(Context context, Intent intent) {  
  4.         String action = intent.getAction();  
  5.         if (action != null) {  
  6.             if (action.equals(Intent.ACTION_SCREEN_ON)) {  
  7.                 // 画面ON時の処理  
  8.   
  9.             }  
  10.         }  
  11.     }  
  12. };  

サービス起動時、停止時にBroadcastReceiverの登録と解除が必要になります。
  1. public class RpService extends Service {  
  2. ...  
  3.     @Override  
  4.     public void onCreate() {  
  5.         super.onCreate();  
  6.   
  7.         // ブロードキャストリスナーの登録  
  8.         // IntentFilterとして、画面オンを示すIntent.ACTION_SCREEN_ONを指定します  
  9.         registerReceiver(mBroadcastReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));  
  10.     }  
  11.     @Override  
  12.     public void onDestroy() {  
  13.         super.onDestroy();  
  14.   
  15.         // ブロードキャストリスナーの登録解除  
  16.         unregisterReceiver(mBroadcastReceiver);  
  17.     }  
  18. ....  
  19. }  


④アクティビティの起動

これはstartActivityを使って起動できるので省略します。


⑤設定再読込要求

設定画面等でサービスに関連する設定を変更した場合に、サービスに設定を再読込するよう要求する必要があります。今回だと、朝に今日のメモは表示しますが、朝のいつに表示するのか時刻を設定できる必要があります。その時刻を変更した際に、サービスも変更した設定情報を読込する必要があります。

これを実現するのに、LocalBroadcastManagerを使うと簡単に実現できます。
BroadcastManagerと同様な機能ですが、ブロードキャスト範囲がアプリ内に限定できます。
アクティビティ側からカスタムIntentを送信して、サービス側で受け取ります。

ブロードキャストを送信する場合は、LocalBroadcastManagerのインスタンスを取得して、sendBroadcastでIntentを送るだけ。
  1. Context context = getApplicationContext();  
  2. LocalBroadcastManager.getInstance(context)  
  3.     .sendBroadcast(new Intent(RpNoteIntent.ACTION_UPDATE_SERVICE));  


サービス側での受け取りは、BroadcastReceiverと同様にリスナーを作成します。
  1. BroadcastReceiver mLocalBroadcastManager = new BroadcastReceiver() {  
  2.     @Override  
  3.     public void onReceive(Context context, Intent intent) {  
  4.         String action = intent.getAction();  
  5.         if (action != null) {  
  6.             if (action.equals(RpNoteIntent.ACTION_UPDATE_SERVICE)) {  
  7.                 // 設定の再読込処理  
  8.   
  9.             }  
  10.         }  
  11.     }  
  12. };  

リスナーの登録・解除は、LocalBroadcastManagerのインスタンスに対して行います。
  1. public class RpService extends Service {  
  2. ...  
  3.     @Override  
  4.     public void onCreate() {  
  5.         super.onCreate();  
  6.   
  7.         // ローカルブロードキャストリスナーの登録  
  8.         LocalBroadcastManager.getInstance(getApplicationContext())  
  9.             .registerReceiver(mLocalBroadcastReceiver, new IntentFilter(RpNoteIntent.ACTION_UPDATE_SERVICE));  
  10.     }  
  11.     @Override  
  12.     public void onDestroy() {  
  13.         super.onDestroy();  
  14.   
  15.         // ローカルブロードキャストリスナーの登録解除  
  16.         LocalBroadcastManager.getInstance(getApplicationContext())  
  17.             .unregisterReceiver(mLocalBroadcastReceiver);  
  18.     }  
  19. ....  
  20. }  


この機能は、メモガキ Ver.0.14.8から実装されます。
ダウンロード (Google Play)


2013年11月25日月曜日

[Macアプリ] PNG画像のサイズを減らすアプリ

ImageAlphaというMac向けアプリを使うことで、PNG画像のサイズを減らせます。
(ダウンロードサイト:http://pngmini.com/

24ビットのPNG画像をパレットを使用した8ビットに変換することでサイズを削減します。色彩豊かな画像の場合は、荒くなってしまいます。アイコン画像などは比較的色が少なく適している。

試しに、画像を256色 に減らしてみると、元の画像と比べて80%削減できました。
 8色に減らすと、88%削減できましたがパッと見で荒いです。
 背景も複数から選択して表示を試すことができます。

僕はAndroidアプリ向けの画像を作成するときに、容量を削減でき重宝しています。
OS X Mavericksでも問題無く動作しています。

2013年10月19日土曜日

[Mac] ダウンロードしたアプリが「壊れているためひらけません」と表示される

Android Studioの新しいバージョンをダウンロードしたけど、「"Android Studio.app"は壊れているため開けません。"ゴミ箱"に入れる必要があります。」と表示されて起動できない。


ダウンロードに失敗したかと思い、再度ダウンロードしましたがダメでした。
試行錯誤している内に、「システム環境設定」のセキュリティ設定を変えることで起動できました。

「ダウンロードしたアプリケーションの実行許可」の設定を「すべてのアプリケーションを許可」に一時的に変更しました。一度アプリ起動すれば、それ以降は設定を戻しても問題なかったです。