2011年11月30日水曜日

[Android][Help]動画のコマ送り・コマ戻しの方法(注:できてないです)

Androidで動画のコマ送り・コマ戻しがしたいのですが、
 数日調べて分からなかったので調査結果だけをメモします。

 ・Androidではフレームごとのデータを取得する方法がAPIでは用意されていない。
  (VideoView や MediaPlayerではそのようなAPIがないということ。)

 ・MediaMetadataRetriever を使えば、指定の時間の画像を取得できそうだが、
試してみると先頭 / 先頭+1のフレームしか取れない。 http://developer.android.com/reference/android/media/MediaMetadataRetriever.html

 MediaMetadataRetriever mmr = new MediaMetadataRetriever();
mmr.setDataSource(getApplicationContext(), uri); int time = 1500; // 取得したい時間(ms)
 Bitmap bitmap = mmr.getFrameAtTime(time);
 //mmr.getFrameAtTime(time, MediaMetadataRetriever.OPTION_NEXT_SYNC); // 先頭の次のフレーム取得する
 //mmr.getFrameAtTime(time, MediaMetadataRetriever.OPTION_PREVIOUS_SYNC); // 先頭フレーム取得する
//mmr.getFrameAtTime(time, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
if(bitmap != null) {
 imageView.setImageBitmap(bitmap);
 } 

・VideoView / MediaPlayer のseekTo()で指定秒数に飛ばしてすぐにpause()すると、
映像が更新されない。
 // ボタン押したら、コマ送り
 button.setOnClickListener(new OnClickListener() {
 @Override
 public void onClick(View v) {
 int pos = mMediaPlayer.getCurrentPosition();
 // mMediaPlayer.start();       // 絵が更新されないので、再生してみる(→更新されない)
 mMediaPlayer.seekTo(pos + 150); // 150ms加算してコマ送り
 mMediaPlayer.start();       // 絵が更新されないので、再生してみる(→更新されない)
 videoView.invalidate();     // 強制的に描画(→更新されない)
 mMediaPlayer.pause();
 }
 } 

・MediaPlayer でシーク完了(setOnSeekCompleteListener)したときに処理しても、映像が更新されない
// ボタン押したら、コマ送り
 button.setOnClickListener(
new OnClickListener() {
 @Override
 public void onClick(View v) { 
int pos = mMediaPlayer.getCurrentPosition();
 mMediaPlayer.seekTo(pos + 150); // 150ms加算してコマ送り
 }
 }

 // button押下後、イベントはきている
mMediaPlayer.setOnSeekCompleteListener(new OnSeekCompleteListener() {
 @Override
 public void onSeekComplete(MediaPlayer mp) {
 if(isSeek) {
 int time = mp.getCurrentPosition();
 mp.start();
 mp.pause();
 }
 }
 });

 なぜなぜ分析してみる
 ・getFrameAtTime()で先頭フレームしか取得できないのはなぜ?
  パラメータの設定の仕方が悪いの? 

・pause中のseekTo()で画像が更新されないのは理解できるとして、
  pause -> start()したときに画像が更新されないのはなぜ?
 だれかヘルプm(__)m

 できたこと、わかったこと
・seekTo()とかgetFrameAtTime()使わずに、コマ送り(風)な処理はできました
 mMediaPlayer.start();  // 再生して、
try {
 Thread.sleep(33);      // 指定秒数スリープしたあとに、
 } catch (InterruptedException e) { }
mMediaPlayer.pause();        // 一時停止する

 ただこの方法だとコマ戻しができないのです。
コマ戻しするには秒数指定するしかないですよね。
困った。どうしましょう

2011年11月25日金曜日

[Android]LoadingImageView

画像をWeb上から取得してImageViewに表示する場合に、
ロード中が分かるようにしたくてViewを作ってみました。

ロード中...
ロード後


プロジェクト一式はGumroadから購入できます。


メインとなるビューです。
 
public class LoadingImageView extends RelativeLayout {

 private Context mContext;
 private ImageView mImageView;
 ProgressBar mProgressBar;
 
    public LoadingImageView(Context context, AttributeSet attrs) {
  super(context, attrs);
  
  this.mContext = context;
  
  LayoutParams layoutParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
  setLayoutParams(layoutParams);
  
  this.mImageView = new ImageView(context);
  this.mImageView.setLayoutParams(layoutParams);
  this.mImageView.setScaleType(ScaleType.CENTER_CROP);
  
  layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
  layoutParams.addRule(CENTER_IN_PARENT);
  this.mProgressBar = new ProgressBar(context, null, android.R.attr.progressBarStyleLarge);
  this.mProgressBar.setLayoutParams(layoutParams);
//  this.mProgressBar.setVisibility(View.GONE);
  
  addView(this.mImageView);
  addView(this.mProgressBar);
 }
使い方は、 MainActivity.class

setContentView(R.layout.main);
loadingImageView = (LoadingImageView)findViewById(R.id.loadingImageView);
  
// Set ImageView default image
loadingImageView.init(R.drawable.init);

initはしてもしなくてもよいです。 ロード前の画像を設定したい場合のみ使います。
 main.xml
  
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
 xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
 >
 <Button 
  android:id="@+id/button"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:text="load image"
     />
 <com.sample.android.LoadingImageView.LoadingImageView
  android:id="@+id/loadingImageView"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     />
</LinearLayout>
 
String imageUrl = "http:// ~~~.jpg";
loadingImageView.loadImage(imageUrl);
loadImage()にURLアドレスを渡すと画像を取得します。
取得完了したら、画像表示してプログレスバーを非表示にします。

2011年11月7日月曜日

日本Androidの会 中国支部 第23回勉強会に行ってきた

2011.11.05 に日本Androidの会 中国支部 第23回勉強会に参加してきました。

当日はあいにくの雨。

内容は、ICS と デザイン。

ICSはさまざまなニュース、記事が出ているので、割愛。

デザインは第1回ということで、色について基本的なところをお勉強。

ベース、メイン、アクセントの3つに分けましょう。が印象に。


今まで、
fragment からも デザインからも逃げてきたので、
そろそろ立ち向かわなければと感じた一日でした。

以上。




PS.
とても充実した内容だったのですが、
すべて書ききれないので、あえて簡素にしてみました。

どんな内容だったかは
cactusさんがまとめてるので、そちらを参照くださいませ。


http://ktake20jp.blogspot.com/2011/11/android-23.html
http://ktake20jp.blogspot.com/2011/11/android-23_06.html

幅480の画像を540x960に表示させる方法

480x60の画像を画面サイズが480x800の端末に表示させるときに、
<ImageView
android:width="480px
android:height="60px"
・・・・
としていたために起こった問題。

この状態で540x960に表示させると、画像が画面いっぱいに広がってくれないのです。
(当然ですが)

そこで、こんな感じにするときれいに幅いっぱいに表示されます。

<ImageView
android:layout_width="fill_parent"
android:layout_height="60px"
android:scaleType="centerCrop"
/>



heightをwrap_contentにすると、画像の上下に余白ができてしまったので、
縦は固定サイズにしないとダメみたいです。

というメモ。

Androidでフリック。に勝手に補足

GPソフトさんのWiki にトラックバックしたかったけど、
できそうになかったので勝手に補足してしまいます。

「Android でフリック」
http://gpsoft.dip.jp/hiki/?Android%A4%C7%A5%D5%A5%EA%A5%C3%A5%AF


画面いっぱいにフリックビューだけを表示させるのなら問題なかったのですが、
今回、下のような感じでフリックビューを表示させようとしたら、コンパイルエラーが出たので、勝手に補足。

===============
ヘッダー

===============


フリックビュー


===============
フッター
===============

<LinearLayout
    android:orientation="vertical"
    ・・・・
    >
    <LinearLayout
        android:id="@+id/layoutHeader"
        ・・・・
         />
    <FlingView
        android:id="@+id/flingView
        ・・・・
        />
    <LinearLayout
        android:id="@+id/layoutFooter"
        ・・・・
         />
/>

このレイアウトだと49行目でコンパイルエラー出ます。
      setLayoutParams(new FrameLayout.LayoutParams(PAGE_WIDTH * PAGES_NUM,

理由はFlingViewの上位のレイアウトがLinearLayoutだから。
という訳で以下のように変更したらよいです。
        setLayoutParams(new LinearLayout.LayoutParams(PAGE_WIDTH * PAGES_NUM,

RelativeLayout にした場合も同じように修正したら大丈夫なはず。

ちなみに、サンプルムービーの上と下の動作は、
23行目のフラグで変更できます。
    private boolean mIsFlingMode = false;



おしまい

Google使いこなしアレコレ

Googleのサービスどれだけ使っているかの棚卸し。
タイトルで言うほど使いこなしてるのかは微妙。

・Gmail
メインとサブの2つのアカウントを持ってます。
携帯(au)メール、サブGmailは受信したら、メインに転送するように設定。
メインのアカウントは、すべてのメールが集約されるようにしています。
その分受信数も多い。
ラベルで振り分けているので、大切なメールを見逃すことはないです。
重要とかは使ってないかも。(使っているけど、あまり見てない)
星も一色のみ。本当に大切なメールのみに使用。

・リーダー
情報収集はすべてリーダーに登録。
Androidからも見れます。
ニュースの確認やブログの更新チェックとか。

・サイト
チームの情報共有に使用。
個人でもAndroidのプロジェクト管理に使用。
ファイルキャビネットに同じファイル名でUploadすれば、バージョン管理できるます。
ただ、過去のコメントが見れないのが難点。

・カレンダー
埋まるほど予定がないので、そこまで使用していません。
祝日見たりとか程度でしょうか。

・ドキュメント
たまにしか使わない。
ドキュメント作成することが少ないので、そこまで使っていません。


・翻訳
ちょくちょく使っていますが、ほかの翻訳サイトと比較しながらといった感じ。

・Youtube
頻繁に。
TBSニュースとか。お気に入りは子供向けの動画で埋まってます。

・書籍
たまにですが、本買う前に見たりします。
本の中身が一部見れたりするので、本屋さんに行って確かめたりしなくてすみます。
便利。

・グループ
メーリングリストです。
チームで使ってましたが、最近使ってません。
情報共有とかに便利。

・Blogger
ここ。

・アラート
1日1回チェックしたいニュースとかで使ってます。
キーワードを入力すると、1日1通メール届くので、わざわざ調べなくてもいい。
リリースしたアプリ名をキーワードにしたりしてます。。

・地図
いつもお世話になっています。


まとめると、今はこんな感じで使ってます。
メールとリーダーとアラートで情報収集、
Bloggerで情報蓄積、
グループとサイトで情報共有、
サイトでファイル管理


Google以外のサービスでは、
情報収集していて気になったことはとりあえずTwitterをURLクリップ代わりに。
気になる記事、役立つ記事はEvernoteでWebクリップに。


参考までに。