ListViewをカスタマイズする
ここが参考になりすぎて、自分で書くことがないのですが、とりあえずメモがわりとして。
実際に動かして表示したコードは、またいつか気が向いたら。
TwitterのTimelineを表示するのはほとんどこれでできちゃいました。
本当は、過去分とかはキャッシュしたりしてsqliteとかに放りこみたいのですが、
スポットでTimeline表示するだけならこれで十分かと。
2011年3月10日木曜日
Twitter Clientとかでよくある、30min agoとか何分前とか。"elapsed time"
これもライブラリがありました。
prettytimeだって。
Convert elapsed timestamps, like, “in 3 minutes!”
elapsed time = 経過時間 というらしい。(恥
ocpsoft-pretty-time-1.0.6.jarを使用しました。
Dateにフォーマットかけて
TextViewにセットするだけです。
簡単簡単。
prettytimeだって。
Convert elapsed timestamps, like, “in 3 minutes!”
elapsed time = 経過時間 というらしい。(恥
ocpsoft-pretty-time-1.0.6.jarを使用しました。
Dateにフォーマットかけて
TextViewにセットするだけです。
PrettyTime p = new PrettyTime(); String prettyTime = p.format(*DateClassのインスタンス*); TextView minutetext = (TextView)view.findViewById(R.id.minutetext); minutetext.setText(prettyTime);
簡単簡単。
Twitter4j でプロフィールのイメージを表示
先の投稿、Twitter4jでxAuth認証 で作成した、TwitterWrapperを使用しています。
Activityの中で。
Activityの中で。
TwitterWrapper twa = new TwitterWrapper();
// TwitterWrapperに用意してあるmethodで、SharedPreferencesに保存してあるTwitterの
// oAuth Token と oAuth Token Secretを使って、アカウントをログイン状態にしています。
twitter = twa.getAuthorizedTwitter(this);
// SharedPreferencesに保存しておいた、設定を取得
SharedPreferences pref =
getSharedPreferences(Values.TWITTER_PREFERENCE_NAME, Activity.MODE_PRIVATE);
// SharedPreferencesに保存しておいた、ScreenNameを取得
String screenName = pref.getString(Values.TWITTER_ID_KEY,"NONE");
try {
// ScreenNameをつかって、Userのデータを取得。
User user = twitter.showUser(screenName);
// ScreenNameをつかって、UserのProfile画像のURLを取得。
URL imageURL = user.getProfileImageURL();
Bitmap profile = null;
// これは、適当にViewのLayoutファイルと紐付けしてください。
ImageView imgv = (ImageView)findViewById(R.id.userIcon);
try {
// BitmapFactory.decodeStreamでビットマップを作成。
profile = BitmapFactory.decodeStream(
imageURL.openConnection().getInputStream());
if ( profile != null ) {
// ちゃんと画像が取得できた時だけ、ImageViewにせってい
imgv.setImageBitmap(profile);
}
} catch (IOException e) {
// 取れなかったら無視、レイアウトファイルに
// デフォルト画像のsrcを設定しておくとそれが出ます。
}
} catch (TwitterException e) {
e.printStackTrace();
}
2011年3月9日水曜日
Twitter4jでxAuth認証
実際にActivityに書いて認証を呼び出すコードを。
めんどくさいので、TwitterWrapperというクラスを作りました。
設定値は、Valuesというクラスに入れてあります。(手抜き
ステップは4つ
1)twitter4jのjarファイルをビルドパスに追加。
2)設定用のValuesクラスを用意。
3)TwitterWrapperを用意。
4)Activityにメソッドを記述。
1)twitter4jのjarファイルをビルドパスに追加。
これは適当にどこか見てみてください。
こことか。JavaでTwitterをOAuth認証して使えるTwitter4jとは
Versionは、twitter4j-android-2.2.1-SNAPSHOT.zip を使用しました。
他必要なライブラリは、oauth-signpost で、signpost-commonshttp4-1.2.1.1.jar とsignpost-core-1.2.1.1.jarです。
2)設定用のValuesクラスを用意。
設定用のValuesクラス
3)TwitterWrapperを用意。
インポート文
クラス
4)Activityにメソッドを記述。
Activityに以下のメソッドを書きます。
インポート文
Activityに以下のメソッドを書き、ボタンに結びつけます。
めんどくさいので、TwitterWrapperというクラスを作りました。
設定値は、Valuesというクラスに入れてあります。(手抜き
ステップは4つ
1)twitter4jのjarファイルをビルドパスに追加。
2)設定用のValuesクラスを用意。
3)TwitterWrapperを用意。
4)Activityにメソッドを記述。
1)twitter4jのjarファイルをビルドパスに追加。
これは適当にどこか見てみてください。
こことか。JavaでTwitterをOAuth認証して使えるTwitter4jとは
Versionは、twitter4j-android-2.2.1-SNAPSHOT.zip を使用しました。
他必要なライブラリは、oauth-signpost で、signpost-commonshttp4-1.2.1.1.jar とsignpost-core-1.2.1.1.jarです。
2)設定用のValuesクラスを用意。
設定用のValuesクラス
public class Values {
public static final String TWITTER_SCREEN_NAME = "じぶんのアカウント";
public static final String TWITTER_CONSUMER_KEY = "自分のConsumerKey";
public static final String TWITTER_CONSUMER_SECRET = "自分のConsumerSecret";
public static final String TWITTER_ACCESS_TOKEN_URL = "https://api.twitter.com/oauth/access_token";
public static final String TWITTER_AUTHORIZE_URL = "https://api.twitter.com/oauth/authorize";
public static final String TWITTER_CALLBACK_URL = "http://てけとうに自分のサイト/";
public static final String TWITTER_PREFERENCE_NAME = "おすきに";
public static final String TWITTER_ID_KEY = "screen_name";
public static final String TWITTER_TOKEN_KEY = "token";
public static final String TWITTER_TOKEN_SECRET_KEY = "tokenSecret";
public static final String TWITTER_ACCESS_TOKEN_KEY = "accessToken";
}
3)TwitterWrapperを用意。
インポート文
import twitter4j.Query; import twitter4j.QueryResult; import twitter4j.Tweet; import twitter4j.Twitter; import twitter4j.TwitterException; import twitter4j.TwitterFactory; import twitter4j.User; import twitter4j.conf.Configuration; import twitter4j.conf.ConfigurationBuilder; import twitter4j.http.AccessToken; import twitter4j.http.OAuthAuthorization; import java.util.List; import android.app.Activity; import android.content.SharedPreferences; import android.util.Log; import android.widget.EditText; // リソースファイルがわり。 import jp.mediba.android.util.Values;
クラス
public class TwitterWrapper {
Twitter twitter;
public TwitterWrapper() {
// do nothing
}
public TwitterWrapper(Twitter twitter) {
this.twitter = twitter;
}
public Twitter getTwitter() {
return twitter;
}
public void setTwitter(Twitter twitter) {
this.twitter = twitter;
}
/**
* Usage: java twitter4j.examples.search.SearchTweets [query]
*/
public List<tweet> searchTweet() {
String str = Values.TWITTER_HASHTAG;
Twitter twitter = new TwitterFactory().getInstance();
try {
Query query = new Query(str);
query.setRpp(30);
QueryResult result = twitter.search(query);
List<tweet> tweets = result.getTweets();
return tweets;
} catch (TwitterException te) {
te.printStackTrace();
Log.w("TWT", "Failed to search tweets: " + te.getMessage());
}
return null;
}
public void authorization(Activity act) throws TwitterException {
ConfigurationBuilder builder =
new ConfigurationBuilder();
builder.setOAuthConsumerKey(Values.TWITTER_CONSUMER_KEY);
builder.setOAuthConsumerSecret(Values.TWITTER_CONSUMER_SECRET);
TwitterFactory factory = new TwitterFactory(builder.build());
String screen_name =
((EditText)act.findViewById(R.id.txtScreenName)).getText().toString();
String password =
((EditText)act.findViewById(R.id.txtPassword)).getText().toString();
Twitter twitter = factory.getInstance(screen_name,password);
AccessToken accessToken = null;
try {
accessToken = twitter.getOAuthAccessToken();
String token = accessToken.getToken();
String tokenSecret = accessToken.getTokenSecret();
SharedPreferences pref =
act.getSharedPreferences(
Values.TWITTER_PREFERENCE_NAME,
Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putString(Values.TWITTER_TOKEN_KEY,token);
editor.putString(Values.TWITTER_TOKEN_SECRET_KEY,tokenSecret);
editor.putString(Values.TWITTER_ID_KEY,screen_name);
editor.commit();
} catch (TwitterException e) {
e.printStackTrace();
throw e;
}
}
public Twitter getAuthorizedTwitter(Activity act) {
SharedPreferences settings =
act.getSharedPreferences(Values.TWITTER_PREFERENCE_NAME, 0);
String token = settings.getString(Values.TWITTER_TOKEN_KEY,"NONE");
String tokenSecret = settings.getString(Values.TWITTER_TOKEN_SECRET_KEY,"NONE");
Twitter twitter = new TwitterFactory().getInstance();
if(twitter.getAuthorization().isEnabled()){
return twitter;
} else {
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.setOAuthConsumerKey(Values.TWITTER_CONSUMER_KEY);
builder.setOAuthConsumerSecret(Values.TWITTER_CONSUMER_SECRET);
builder.setOAuthAccessToken(token);
builder.setOAuthAccessTokenSecret(tokenSecret);
Configuration configuration = builder.build();
TwitterFactory factory = new TwitterFactory();
try {
twitter = factory.getInstance(new OAuthAuthorization(configuration));
} catch (java.lang.StringIndexOutOfBoundsException e) {
return null;
}
if(twitter.getAuthorization().isEnabled()){
return twitter;
} else {
return null;
}
}
}
}
4)Activityにメソッドを記述。
Activityに以下のメソッドを書きます。
インポート文
import twitter4j.TwitterException; import jp.mediba.android.util.TwitterWrapper;
Activityに以下のメソッドを書き、ボタンに結びつけます。
public void pushAuth(View v) {
TwitterWrapper tw = new TwitterWrapper();
AlertDialog.Builder abuilder = new AlertDialog.Builder(this);
try {
// ActivityそのものをTwitterWrapperに渡しています。
tw.authorization(this);
// 設定が完了したら、ダイアログを出す。
abuilder.setMessage( R.string.dialog_api_twitter_setting_done_title )
.setCancelable(false)
.setPositiveButton( R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
// ダイアログのOKをおしたら、別画面に遷移。
goTweet();
}
});
} catch (TwitterException e) {
e.printStackTrace();
// なんかエラーが起きたら、ダイアログを出す。
abuilder.setMessage( R.string.error_api_twitter_login )
.setCancelable(false)
.setPositiveButton( R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
}
AlertDialog alert = abuilder.create();
alert.show();
}
// 遷移したいActivityをセットして、画面遷移するロジックは外出ししておく。
public void goTweet() {
Intent intent = new Intent(this, ActTweet.class);
startActivity(intent);
finish();
}
Twitter xAuth申請で疲れた…。
Androidにて、Twitter連携アプリを作成し、xAuthに対応させてみました。
その際、xAuthの申請で、非常に時間がかかったので、まとめ。
最初、アプリケーション名と、情報だけ書いて、開発中ですとメール送ったら、
これでできない?「http://dev.twitter.com/pages/oauth_single_token 」
とお返事が帰ってきました。
先に、oAuthのTokenとTokenSecretをとっておいて、アプリに埋め込んじゃえばoAuthで投稿できるよという意味らしいです。
しかしこれでは、アプリでユーザーがログインして、そのアカウントで投稿するってのができません。
xAuthの許諾は真面目に審査してるみたいです。
開発目的での許諾は行わないとのメールももらいました。
ということで、xAuthの許可を得るのに必要な準備事項をまとめておきます。
1)oAuthアプリケーションの登録。
Webでは下記の場所から登録できます。
「設定」>「連携アプリ」>「連携アプリの追加と設定は『こちら』から変更できます。」
2)アプリのログイン画面とTweet画面、TLの画面をキャプチャしてPDFか何かで、説明文をまとめたもの。
Twitterのチケットサーバーは添付ファイルに対応していないようなので、PDFや画像はどこか公開できるサーバーに配置しておきましょう。
この状態で、以下のメールをapi@twitter.comにおくります。
その際、xAuthの申請で、非常に時間がかかったので、まとめ。
最初、アプリケーション名と、情報だけ書いて、開発中ですとメール送ったら、
これでできない?「http://dev.twitter.com/pages/oauth_single_token 」
とお返事が帰ってきました。
先に、oAuthのTokenとTokenSecretをとっておいて、アプリに埋め込んじゃえばoAuthで投稿できるよという意味らしいです。
しかしこれでは、アプリでユーザーがログインして、そのアカウントで投稿するってのができません。
xAuthの許諾は真面目に審査してるみたいです。
開発目的での許諾は行わないとのメールももらいました。
ということで、xAuthの許可を得るのに必要な準備事項をまとめておきます。
1)oAuthアプリケーションの登録。
Webでは下記の場所から登録できます。
「設定」>「連携アプリ」>「連携アプリの追加と設定は『こちら』から変更できます。」
2)アプリのログイン画面とTweet画面、TLの画面をキャプチャしてPDFか何かで、説明文をまとめたもの。
Twitterのチケットサーバーは添付ファイルに対応していないようなので、PDFや画像はどこか公開できるサーバーに配置しておきましょう。
この状態で、以下のメールをapi@twitter.comにおくります。
(英文が変なのは、気にしないでください。www )
---
Hello.
I'm a developer of "アプリケーション名".
"アプリケーション名" is a android application, for tweeting some messages.
I want to use this application for a multi users' twitter client.
I do not want to use android.webkit.WebView because of Userbility.
I send this application screen capture and explain the reason of using xAuth.
URL:{スクリーンキャプチャのURLとか。}
Please apply this app to use xAuth.
Application Name: {アプリケーション名}
App Source Code : (now developping)
My account : @{ツイッターのスクリーンネーム}
oAuth Clients : http://twitter.com/oauth_clients/details/{oAuth申請のページのID}
Thank you.
---
これで一発で通るはず。
あとは、Twitterにログインした状態で、
のステータスを確認していましょう。
ちなみに、なんでWebViewを使わないか、ってところの文章は、「日本人アンドロイドに慣れてないの。」としていましたが、これさすがに汎用的に使われると如何かと思うので、文章を「because of Userbility.」に変えてあります。
申請の際に仕様した、PDFも少々変えてありますが、添付しておきます。
(多分ちゃんとしたスクリーンキャプチャのほうが、いいはず。)
2011年2月22日火曜日
au IS04 (REGZA Phone) がADBでデバイス認識されない(MAC OS10.6.6)
タイトルの通りですが、MAC OSXでのAndroid開発環境では、通常は端末をデバッグモードでUSB接続した場合、とくにドライバのインストール作業などを行わずに使用することができました。
(過去に問題なく接続できた端末)
・HTC HT03A
・HTC Desire
・SonyEricsson EXPERIA
・SHARP IS01
・SHARP IS03
今回、TOSHIBA IS04 で実機検証する機会があり、今までと同じようにUSB接続してみたところADB上で認識されません。
WEB上で色々と調べた結果、以下の方法で解決したのでまとめておきます。
1. .androidディレクトリ(だいたいはユーザディレクトリの直下にあります)
にadb_usb.iniというファイルがあるか確認
2. なければ adb_usb.ini の作成
こちらのサイトを参考にさせていただきました。
http://d.hatena.ne.jp/rmiya/20091109
3. adb_usb.ini にIS04のベンダーID
0x0930
を追加
4. ADBを再起動
端末を接続し、 adb devices コマンド、またはEclipeなどのUI上で端末が表示されれば成功です。
ちなみに、Windows向けにはドライバが配布されているようです。
(過去に問題なく接続できた端末)
・HTC HT03A
・HTC Desire
・SonyEricsson EXPERIA
・SHARP IS01
・SHARP IS03
今回、TOSHIBA IS04 で実機検証する機会があり、今までと同じようにUSB接続してみたところADB上で認識されません。
WEB上で色々と調べた結果、以下の方法で解決したのでまとめておきます。
1. .androidディレクトリ(だいたいはユーザディレクトリの直下にあります)
にadb_usb.iniというファイルがあるか確認
2. なければ adb_usb.ini の作成
こちらのサイトを参考にさせていただきました。
http://d.hatena.ne.jp/rmiya/20091109
3. adb_usb.ini にIS04のベンダーID
0x0930
を追加
4. ADBを再起動
端末を接続し、 adb devices コマンド、またはEclipeなどのUI上で端末が表示されれば成功です。
ちなみに、Windows向けにはドライバが配布されているようです。
2011年1月28日金曜日
Android開発 - 画面の縦横を検知して回転するボタンを作る(3)
Android開発 - 画面の縦横を検知して回転するボタンを作る(1)
Android開発 - 画面の縦横を検知して回転するボタンを作る(2)
Javaのコードは2種類
・Main.java (メインのアクティビティクラス)
・AnimationController.java (回転アニメーションの制御)
になります。
AnimationController.java
import android.hardware.SensorEvent;
import android.view.animation.RotateAnimation;
import android.widget.ImageButton;
public class AnimationController {
boolean yoko = false;
float touchY;
long ANIM_ROTATE_SPEED = 200;
public void rotateCube(SensorEvent event, ImageButton[] img) {
if (!yoko && event.values[2] > 60 && event.values[2] < 80) {
for (ImageButton target: img){
RotateAnimation rotate = new RotateAnimation(0, 90, target.getWidth()/2, target.getHeight()/2);
rotate.setDuration(ANIM_ROTATE_SPEED);
rotate.setFillAfter(true);
target.startAnimation(rotate);
}
yoko = true;
}
if (yoko && event.values[2] > -10 && event.values[2] < 10) {
for (ImageButton target: img){
RotateAnimation rotate = new RotateAnimation(90, 0, target.getWidth()/2, target.getHeight()/2);
rotate.setDuration(ANIM_ROTATE_SPEED);
rotate.setFillAfter(true);
target.startAnimation(rotate);
}
yoko = false;
}
}
}
Main.java
import java.util.List;
import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.RotateAnimation;
import android.widget.ImageButton;
public class Main extends Activity implements SensorEventListener, OnClickListener{
AnimationController animationController = new AnimationController();
SensorManager mSensorManager = null;
private boolean mRegisteredSensor;
float touchY;
float moveY;
boolean yoko = false;
RotateAnimation rotateAnimation;
ImageButton button01;
ImageButton button02;
ImageButton button03;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mRegisteredSensor = false;
button01 = (ImageButton)findViewById(R.id.button01);
button02 = (ImageButton)findViewById(R.id.button02);
button03 = (ImageButton)findViewById(R.id.button03);
}
@Override
protected void onResume() {
List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
if (sensors.size() > 0) {
Sensor sensor = sensors.get(0);
mRegisteredSensor = mSensorManager.registerListener(this,sensor,SensorManager.SENSOR_DELAY_FASTEST);
}
super.onResume();
}
@Override
protected void onPause() {
if (mRegisteredSensor) {
mSensorManager.unregisterListener(this);
mRegisteredSensor = false;
}
super.onPause();
}
@Override
protected void onStop() {
mSensorManager.unregisterListener(this);
super.onStop();
}
@Override
public void onClick(View v) {
switch( v.getId() ){
case R.id.button01:
//ボタンタッチ時の処理
break;
case R.id.button02:
//ボタンタッチ時の処理
break;
case R.id.button03:
//ボタンタッチ時の処理
break;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
ImageButton[] img = {button01,button02,button03};
animationController.rotateCube(event, img);
}
}
}
Main.java の onSensorChanged → Sensor.TYPE_ORIENTATIONで傾きを検知し、SensorEvent と 対象となるボタンを AnimationController に渡しています。
センサーイベントの event.values[2] でY軸の傾きの値が取れます。
event.values[2] = 60〜80 でボタンを横向きに、
event.values[2] = -10〜10 でボタンを縦向きにアニメーションさせていますが、このあたりの設定は改善の余地がありそうです。
センサーイベントの実装は、以下のサイトを参考にさせていただきました。
http://www.adakoda.com/android/000182.html
Android開発 - 画面の縦横を検知して回転するボタンを作る(2)
Javaのコードは2種類
・Main.java (メインのアクティビティクラス)
・AnimationController.java (回転アニメーションの制御)
になります。
AnimationController.java
import android.hardware.SensorEvent;
import android.view.animation.RotateAnimation;
import android.widget.ImageButton;
public class AnimationController {
boolean yoko = false;
float touchY;
long ANIM_ROTATE_SPEED = 200;
public void rotateCube(SensorEvent event, ImageButton[] img) {
if (!yoko && event.values[2] > 60 && event.values[2] < 80) {
for (ImageButton target: img){
RotateAnimation rotate = new RotateAnimation(0, 90, target.getWidth()/2, target.getHeight()/2);
rotate.setDuration(ANIM_ROTATE_SPEED);
rotate.setFillAfter(true);
target.startAnimation(rotate);
}
yoko = true;
}
if (yoko && event.values[2] > -10 && event.values[2] < 10) {
for (ImageButton target: img){
RotateAnimation rotate = new RotateAnimation(90, 0, target.getWidth()/2, target.getHeight()/2);
rotate.setDuration(ANIM_ROTATE_SPEED);
rotate.setFillAfter(true);
target.startAnimation(rotate);
}
yoko = false;
}
}
}
Main.java
import java.util.List;
import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.RotateAnimation;
import android.widget.ImageButton;
public class Main extends Activity implements SensorEventListener, OnClickListener{
AnimationController animationController = new AnimationController();
SensorManager mSensorManager = null;
private boolean mRegisteredSensor;
float touchY;
float moveY;
boolean yoko = false;
RotateAnimation rotateAnimation;
ImageButton button01;
ImageButton button02;
ImageButton button03;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mRegisteredSensor = false;
button01 = (ImageButton)findViewById(R.id.button01);
button02 = (ImageButton)findViewById(R.id.button02);
button03 = (ImageButton)findViewById(R.id.button03);
}
@Override
protected void onResume() {
List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
if (sensors.size() > 0) {
Sensor sensor = sensors.get(0);
mRegisteredSensor = mSensorManager.registerListener(this,sensor,SensorManager.SENSOR_DELAY_FASTEST);
}
super.onResume();
}
@Override
protected void onPause() {
if (mRegisteredSensor) {
mSensorManager.unregisterListener(this);
mRegisteredSensor = false;
}
super.onPause();
}
@Override
protected void onStop() {
mSensorManager.unregisterListener(this);
super.onStop();
}
@Override
public void onClick(View v) {
switch( v.getId() ){
case R.id.button01:
//ボタンタッチ時の処理
break;
case R.id.button02:
//ボタンタッチ時の処理
break;
case R.id.button03:
//ボタンタッチ時の処理
break;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
ImageButton[] img = {button01,button02,button03};
animationController.rotateCube(event, img);
}
}
}
Main.java の onSensorChanged → Sensor.TYPE_ORIENTATIONで傾きを検知し、SensorEvent と 対象となるボタンを AnimationController に渡しています。
センサーイベントの event.values[2] でY軸の傾きの値が取れます。
event.values[2] = 60〜80 でボタンを横向きに、
event.values[2] = -10〜10 でボタンを縦向きにアニメーションさせていますが、このあたりの設定は改善の余地がありそうです。
センサーイベントの実装は、以下のサイトを参考にさせていただきました。
http://www.adakoda.com/android/000182.html
2011年1月25日火曜日
Android開発 - 画面の縦横を検知して回転するボタンを作る(2)
Android開発 - 画面の縦横を検知して回転するボタンを作る(1)
まずはManifestファイルから
■AndroidManifest.xml
Activityタグ内で android:screenOrientation="portrait" を指定し、画面自体は縦表示で固定します。
続いてレイアウトファイル
■Main.xml
サンプルではアプリランチャー的なイメージで ImageButton を使いますが、ImageViewやTextView等でも作成可能です。
次回は実際にアニメーションを行うコードを作っていきます。
Android開発 - 画面の縦横を検知して回転するボタンを作る(3)
まずはManifestファイルから
■AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="jp.mediba.android.RotateCube"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon"
android:label="@string/app_name"
android:debuggable="true" >
<activity android:name=".Main"
android:label="@string/app_name"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="4" />
</manifest>
Activityタグ内で android:screenOrientation="portrait" を指定し、画面自体は縦表示で固定します。
続いてレイアウトファイル
■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="fill_parent"
android:layout_height="fill_parent"
>
<ImageButton
android:id="@+id/button01"
android:src="@drawable/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@null"
android:layout_marginTop="60dp"
></ImageButton>
<ImageButton
android:id="@+id/button02"
android:src="@drawable/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@null"
android:layout_marginTop="60dp"
></ImageButton>
<ImageButton
android:id="@+id/button03"
android:src="@drawable/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@null"
android:layout_marginTop="60dp"
></ImageButton>
</LinearLayout>
サンプルではアプリランチャー的なイメージで ImageButton を使いますが、ImageViewやTextView等でも作成可能です。
次回は実際にアニメーションを行うコードを作っていきます。
Android開発 - 画面の縦横を検知して回転するボタンを作る(3)
Android開発 - 画面の縦横を検知して回転するボタンを作る(1)
Androidアプリの開発で、主にUI関係の話をしていると、
「iPhoneぽく」「iPhoneみたいに・・・」といった要望がしばしば出てきます。
直感的でわかりやすく、且つ格好良いインターフェースという点においてはAndroidよりもiOSに分があるのが現状のようです。
今回は、「画面の縦横切替をアニメーションで多少なりとも格好良く見せる」チャレンジをしてみます。
通常、下のような画面の場合
端末を横向きにすると、
このような画面に切り替わります。
これを
・レイアウトそのものは縦画面で固定
・プログラム内で端末の動きを検知しアイコン画像がアニメーションで90度回転
・アニメーション後は以下のような表示に
してみたいと思います。
続きは次回。
Android開発 - 画面の縦横を検知して回転するボタンを作る(2)
「iPhoneぽく」「iPhoneみたいに・・・」といった要望がしばしば出てきます。
直感的でわかりやすく、且つ格好良いインターフェースという点においてはAndroidよりもiOSに分があるのが現状のようです。
今回は、「画面の縦横切替をアニメーションで多少なりとも格好良く見せる」チャレンジをしてみます。
通常、下のような画面の場合
端末を横向きにすると、
このような画面に切り替わります。
これを
・レイアウトそのものは縦画面で固定
・プログラム内で端末の動きを検知しアイコン画像がアニメーションで90度回転
・アニメーション後は以下のような表示に
してみたいと思います。
続きは次回。
Android開発 - 画面の縦横を検知して回転するボタンを作る(2)
2010年12月10日金曜日
2010年11月29日月曜日
傾き、加速度の手振れノイズをフィルターする
人間の手の震えもありますが、端末で取れる加速度センサーの値は、結構細かく震えています。
この加速度センサーの値をもとにLinearで中心にあるボールを動かしたかったのですが、この震えのせいで、
きれいに移動しないで、ぴょこぴょこと跳ねているような動きに見えてしまうので困りました。
センサーの精度かと思って、そちらを調査してみたり、
アニメーションの処理飛びなのかと思ってログを見てみたりしていたのですが、
特に解決策は見つからず。
結局のところこのブレを減らすための解決策が必要だろうと推測して、ノイズフィルターを探していたところ身近なところに解決策がありました。
DJミキサーでよくある、ハイパスフィルターとローパスフィルターです。
ハイパスフィルターは、つまみを回すとだんだんシャキシャキの音になってくあれですw。
ローパスフィルターは、つまみを回すとだんだんモコモコの音になってくあれですw。
WikiPedia ローパスフィルター(ハイカット)
ローパスフィルタ(Low-pass filter: LPF)はフィルタ回路の一種で、低周波を良く通し、ある遮断周波数より高い周波数の帯域を通さない(減衰させる)フィルタである。
WikiPedia ハイパスフィルター(ローカット)
ハイパスフィルタ(High-pass filter: HPF)はフィルタ回路の一種で、高周波を良く通し、遮断周波数より低い周波数の帯域を通さない(減衰させる)フィルタである。 日本語では「高域通過濾波器」とも言われる。また英語では「low-cut filter」とも言われ、これは「bass-cut filter」または「rumble filter」としてオーディオ機器などで使用される。
加速度は、重力加速度+手振れなどの実際の端末の動きが加速度が影響してきます。
あるXYZで考えてどれか一方向についての変化
重力加速度の変化:端末の大体の傾きになりますので周波数で考えるとだんだん傾いていれば低い周波数です。
端末の動きの変化:手振れなので重力加速度の変化より高い周波数のノイズになります。
ぴょこぴょこと動いてしまうのは、「端末の動きの変化」が影響しているので、高い周波数をカットすればいい。すなわち低い周波数だけ通せばいいということになります。
ってことで、ロジック。
一つ前の値と比較しながら、値を取ります。
XYだけの例です。
部分的に抜き出すとわけわからなくなったので、全部載せます。
イメージを最初に真ん中において、ローパスフィルタをかけた加速度で、イメージを移動しています。
この加速度センサーの値をもとにLinearで中心にあるボールを動かしたかったのですが、この震えのせいで、
きれいに移動しないで、ぴょこぴょこと跳ねているような動きに見えてしまうので困りました。
センサーの精度かと思って、そちらを調査してみたり、
アニメーションの処理飛びなのかと思ってログを見てみたりしていたのですが、
特に解決策は見つからず。
結局のところこのブレを減らすための解決策が必要だろうと推測して、ノイズフィルターを探していたところ身近なところに解決策がありました。
DJミキサーでよくある、ハイパスフィルターとローパスフィルターです。
ハイパスフィルターは、つまみを回すとだんだんシャキシャキの音になってくあれですw。
ローパスフィルターは、つまみを回すとだんだんモコモコの音になってくあれですw。
WikiPedia ローパスフィルター(ハイカット)
ローパスフィルタ(Low-pass filter: LPF)はフィルタ回路の一種で、低周波を良く通し、ある遮断周波数より高い周波数の帯域を通さない(減衰させる)フィルタである。
WikiPedia ハイパスフィルター(ローカット)
ハイパスフィルタ(High-pass filter: HPF)はフィルタ回路の一種で、高周波を良く通し、遮断周波数より低い周波数の帯域を通さない(減衰させる)フィルタである。 日本語では「高域通過濾波器」とも言われる。また英語では「low-cut filter」とも言われ、これは「bass-cut filter」または「rumble filter」としてオーディオ機器などで使用される。
加速度は、重力加速度+手振れなどの実際の端末の動きが加速度が影響してきます。
あるXYZで考えてどれか一方向についての変化
重力加速度の変化:端末の大体の傾きになりますので周波数で考えるとだんだん傾いていれば低い周波数です。
端末の動きの変化:手振れなので重力加速度の変化より高い周波数のノイズになります。
ぴょこぴょこと動いてしまうのは、「端末の動きの変化」が影響しているので、高い周波数をカットすればいい。すなわち低い周波数だけ通せばいいということになります。
ってことで、ロジック。
一つ前の値と比較しながら、値を取ります。
XYだけの例です。
部分的に抜き出すとわけわからなくなったので、全部載せます。
イメージを最初に真ん中において、ローパスフィルタをかけた加速度で、イメージを移動しています。
package jp.mediba.android.xxxxxx;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.util.Log;
import android.widget.ImageView;
public class PointViewOverlay extends ImageView {
private Matrix mMatrix = new Matrix();
private Matrix mSavedMatrix = new Matrix();
private float[] currentOrientationValues = {0.0f, 0.0f};
private PointF startPoint = new PointF();
private ImageView imageView;
private int frameWidth = 0;
private int frameHeight = 0;
public PointViewOverlay(Context context) {
super(context);
// TODO 自動生成されたコンストラクター・スタブ
}
public void setImageView(ImageView imageView) {this.imageView = imageView;}
public void setFrameSize(int frameWidth, int frameHeight) {
this.frameWidth = frameWidth;
this.frameHeight = frameHeight;
}
public void resetStartPoint() {
mMatrix.set(mSavedMatrix);
this.startPoint = new PointF((float)this.frameWidth/2,(float)this.frameHeight/2);
mMatrix.postTranslate(this.startPoint.x, this.startPoint.y);
imageView.setImageMatrix(mMatrix);
Log.v("resetStartPoint.",String.valueOf("X:" + this.startPoint.x) + "Y:" + String.valueOf(this.startPoint.y));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO 自動生成されたメソッド・スタブ
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public void animateView( SensorEvent event ) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
// Lowpass Filter ハイカット これ!
currentOrientationValues[0] = event.values[0] * 0.1f + currentOrientationValues[0] * (1.0f - 0.1f);
currentOrientationValues[1] = event.values[1] * 0.1f + currentOrientationValues[1] * (1.0f - 0.1f);
// 重力加速度
float accX = currentOrientationValues[0];
float accY = currentOrientationValues[1];
// 横画面なのでちょっと大きめにしました。
float moveX = Math.round(accY*48);
float moveY = Math.round(accX*32);
float pointX = this.startPoint.x+moveX;
float pointY = this.startPoint.y+moveY;
mMatrix.set(mSavedMatrix);
mMatrix.postTranslate(pointX,pointY);
imageView.setImageMatrix(mMatrix);
Log.v("animateView","pointX,pointY"+String.valueOf(pointX)+","+String.valueOf(pointY));
}
}
}
2010年11月16日火曜日
DroidDraw Android LayoutXMLのWYSIWYGエディタ
http://www.droiddraw.org/
http://code.google.com/p/droiddraw/
機能を完全には使っていないのですが、レイアウトがWYSIWYGでDrag&Dropできて便利です。
Mac OS X, Windows, Linuxのマルチプラットフォームサポートしています。
使い方さえ覚えればもしかするとデザイナさんでも一人でUI作れるかも?
ADTについているレイアウトエディタだとRelativeLayoutの中に入れた、2つのLinearLayoutを左右にふって上合わせにするプロパティーがどこにあるか見つけにくい(ってかあるのか?)のですが、それをマウス操作で上にあわせたり下にあわせたりできます。
(* (ADT) Android Development Tools for the Eclipse IDE )
これだけで、非常にストレスが減る!
Eclipseと連携して操作する所まで入っていないのですが、ファイルの場所を合わせればリソースファイルも読めるようです。
出力は、.apkパッケージで出力したり、XML単体で出力したりできます。
GUIで要素のIDを付ける操作は、いまいち使い勝手が悪いので、ひと通りの配置まで決めたあとは、XMLをEclipseのADTに貼りつけて、名前を付け直したりしています。
どう書いたらうまく並べられるのかの勉強替わりにもなりますね。
ひと通り慣れたら、プロパティーが覚えられそうなのでHTMLのようにタグがきができるようになれるような気がしています。
一点分かりにくいのが、Layout要素を入れ子にすると、外を囲むレイアウトがなんだったかが、GUI上から見えにくいところかな。
でも何にせよ使う利点は十分にあります。
MoonGiftの紹介記事
http://code.google.com/p/droiddraw/
機能を完全には使っていないのですが、レイアウトがWYSIWYGでDrag&Dropできて便利です。
Mac OS X, Windows, Linuxのマルチプラットフォームサポートしています。
使い方さえ覚えればもしかするとデザイナさんでも一人でUI作れるかも?
ADTについているレイアウトエディタだとRelativeLayoutの中に入れた、2つのLinearLayoutを左右にふって上合わせにするプロパティーがどこにあるか見つけにくい(ってかあるのか?)のですが、それをマウス操作で上にあわせたり下にあわせたりできます。
(* (ADT) Android Development Tools for the Eclipse IDE )
これだけで、非常にストレスが減る!
Eclipseと連携して操作する所まで入っていないのですが、ファイルの場所を合わせればリソースファイルも読めるようです。
出力は、.apkパッケージで出力したり、XML単体で出力したりできます。
GUIで要素のIDを付ける操作は、いまいち使い勝手が悪いので、ひと通りの配置まで決めたあとは、XMLをEclipseのADTに貼りつけて、名前を付け直したりしています。
どう書いたらうまく並べられるのかの勉強替わりにもなりますね。
ひと通り慣れたら、プロパティーが覚えられそうなのでHTMLのようにタグがきができるようになれるような気がしています。
一点分かりにくいのが、Layout要素を入れ子にすると、外を囲むレイアウトがなんだったかが、GUI上から見えにくいところかな。
でも何にせよ使う利点は十分にあります。
MoonGiftの紹介記事
2010年11月15日月曜日
XCodeとInterfaceBuilderで10分でモックアプリを作る方法(3)
前回の続き。
全部で5回の予定です。
おそらく5回書き終わってからでないとあまり意味のない記事になっちゃいました…。
でも頑張ります。
では、ボタンを押したら画面遷移する動作を紐付けていきましょう。
まずは、XCodeの左側のツリーから、一番最初の画面の .xib ファイルをダブルクリックして、IB(InterfaceBuilderを立ち上げます。)
立ち上げると、こんな状態です。
まず、メインの画面にボタンを押したときの操作を定義します。
先に、それぞれのボタンを押したときの操作を決めておきましょう。
3つボタンがあるので、こんな名前にしてみました。
ヘルプへ = changeViewHelp
設定へ = changeViewSetting
実行へ = changeViewMain
2.「File's Owner」に動作の名前を定義する。
これらを、IBをつかって定義していきます。
これからウィンドウを行ったり来たりするので混乱しないように。www
Document 画面の「File's Owner」をクリックします。
そうすると、右側の「インスペクタ」でこの画面に対するいろいろな設定ができるようになります。が、ここではまだちゃんとは使いません。w
上部にタブが4つ見えると思いますが、( i ) の所を選択してください。
それを確認したら、「Class」のボックスにある、矢印をクリックしてください。
そうすると今度は、左側の「Library」のWindowの下側に、 「NavigationTestViewController」というボックスが現れます。
このプルダウンを「Actions」に合わせてください。
その状態で、「+」のボタンが下に現れます。
これをクリックして、3つのボタン操作を定義します。
こんな感じに。
3.「File's Owner」に動作の名前を定義したものを保存する。
これを、実際のファイルに保存します。
下のプルダウンから、「Write Updated Class File」を選択してください。
保護んウィンドウがでるのでこれで、Saveを押します。
もうあるけど、どうする?って聞かれますので「Replace」を押してください。
(置き換えられちゃいます。w まだファイルにはなにもかいていないので、大丈夫。)
4.ボタンの動作を「File's Owner」につなげる。
IBで「実行へ」のボタンをクリックして触ってください。
そうすると、右側の「インスペクタ」でボタンに対するいろいろな設定ができるようになります。
ここで、右側の「Connections」のタブを表示します。
ここには、ボタンの動作がすでに定義されており、押したら、どうとか、おして、指が離れたらどうとか、いろいろつなぐことができます。
ここでは、押して、指が離れたら、画面遷移するということにして、「Touch Up Inside」を使います。
これの右側にある◯をクリックし、ドラッグして、「Document」ウィンドウの「File's Owner」につなげます。「File's Owner」にまで、持って行ってマウスを外します。
と、グレーのサブウィンドウが現れるので、「実行へ」に対応する
changeViewMainをクリックします。
ちゃんとつながると、「Connections」の画面がこんなふうになります。
この状態で、.xibファイルを保存してください。
続いて、XCodeに戻り、画面遷移のプログラムを書きます。
そろそろ時間切れなので、また次…。中途半端でごめんなさい。
全部で5回の予定です。
おそらく5回書き終わってからでないとあまり意味のない記事になっちゃいました…。
でも頑張ります。
では、ボタンを押したら画面遷移する動作を紐付けていきましょう。
まずは、XCodeの左側のツリーから、一番最初の画面の .xib ファイルをダブルクリックして、IB(InterfaceBuilderを立ち上げます。)
立ち上げると、こんな状態です。
1.動作の名前を決める
まず、メインの画面にボタンを押したときの操作を定義します。
先に、それぞれのボタンを押したときの操作を決めておきましょう。
3つボタンがあるので、こんな名前にしてみました。
ヘルプへ = changeViewHelp
設定へ = changeViewSetting
実行へ = changeViewMain
2.「File's Owner」に動作の名前を定義する。
これらを、IBをつかって定義していきます。
これからウィンドウを行ったり来たりするので混乱しないように。www
Document 画面の「File's Owner」をクリックします。
そうすると、右側の「インスペクタ」でこの画面に対するいろいろな設定ができるようになります。が、ここではまだちゃんとは使いません。w
上部にタブが4つ見えると思いますが、( i ) の所を選択してください。
その内容の一番上の「Class」のところに 「NavigationTestViewController」という名前が出ていると思います。これが、この画面の操作の統括をするプログラムの名前です。
(対応して、XCodeの中にも同じ名前のxxx.h xxx.mというファイルがあります。)
それを確認したら、「Class」のボックスにある、矢印をクリックしてください。
そうすると今度は、左側の「Library」のWindowの下側に、 「NavigationTestViewController」というボックスが現れます。
このプルダウンを「Actions」に合わせてください。
その状態で、「+」のボタンが下に現れます。
これをクリックして、3つのボタン操作を定義します。
こんな感じに。
3.「File's Owner」に動作の名前を定義したものを保存する。
これを、実際のファイルに保存します。
下のプルダウンから、「Write Updated Class File」を選択してください。
保護んウィンドウがでるのでこれで、Saveを押します。
もうあるけど、どうする?って聞かれますので「Replace」を押してください。
(置き換えられちゃいます。w まだファイルにはなにもかいていないので、大丈夫。)
4.ボタンの動作を「File's Owner」につなげる。
次に、それぞれのボタンを押した操作を紐付けます。
まずに、「実行へ」のボタンを、Mainの画面機能につなげます。IBで「実行へ」のボタンをクリックして触ってください。
そうすると、右側の「インスペクタ」でボタンに対するいろいろな設定ができるようになります。
ここで、右側の「Connections」のタブを表示します。
ここには、ボタンの動作がすでに定義されており、押したら、どうとか、おして、指が離れたらどうとか、いろいろつなぐことができます。
ここでは、押して、指が離れたら、画面遷移するということにして、「Touch Up Inside」を使います。
これの右側にある◯をクリックし、ドラッグして、「Document」ウィンドウの「File's Owner」につなげます。「File's Owner」にまで、持って行ってマウスを外します。
と、グレーのサブウィンドウが現れるので、「実行へ」に対応する
changeViewMainをクリックします。
ちゃんとつながると、「Connections」の画面がこんなふうになります。
この状態で、.xibファイルを保存してください。
続いて、XCodeに戻り、画面遷移のプログラムを書きます。
そろそろ時間切れなので、また次…。中途半端でごめんなさい。
10分は無理だなこれ。www
スゲー速さで作業してYoutubeではや回しビデオでもアップして帳尻合わせやろうかと思ってきました。wwww
2010年11月12日金曜日
2010年11月11日木曜日
アプリの起動時に、着信音量とMedia音量をあわせる
メタルメガネ(Metal Megane)の「森羅万象おみくじうらない」ですが、Android版で音が出るようになりました。
着信音の音量に合わせて音量コントロールしていたら音楽がイヤフォンと本体の両方から出るようになってしまいました。
さすがにこれは、iPhoneユーザー的にはありえないなーと思ったのですが、Androidでは結構浸透している仕様のようですね。
ということで、これを避けるために、AudioManagerのストリームをAudioManager.STREAM_MUSICに、再度変更したのですがこうすると今度は、着信音量をオフにしていても、アプリが立ち上がると音量が、音楽再生用の音量として出ます。
着信音量をOFFにして、音楽を聞いたときに、音量をUPすると、
AudioManager.STREAM_MUSICとして効果音再生しているアプリは効果音が再生されてしまいます。
さすがにこれだと、iPhoneから移行してきたユーザーや、ガラケーから移行してきたユーザーはビックリするんじゃないかということで、アプリの起動時には、着信音量が0だったら、音楽再生音量を0にするという処理を入れました。
ということで、ソースコード。
この実装は、android.app.Applicationクラスのサブクラスとして、onCreate時に呼び出しています。
着信音の音量に合わせて音量コントロールしていたら音楽がイヤフォンと本体の両方から出るようになってしまいました。
さすがにこれは、iPhoneユーザー的にはありえないなーと思ったのですが、Androidでは結構浸透している仕様のようですね。
ということで、これを避けるために、AudioManagerのストリームをAudioManager.STREAM_MUSICに、再度変更したのですがこうすると今度は、着信音量をオフにしていても、アプリが立ち上がると音量が、音楽再生用の音量として出ます。
着信音量をOFFにして、音楽を聞いたときに、音量をUPすると、
AudioManager.STREAM_MUSICとして効果音再生しているアプリは効果音が再生されてしまいます。
さすがにこれだと、iPhoneから移行してきたユーザーや、ガラケーから移行してきたユーザーはビックリするんじゃないかということで、アプリの起動時には、着信音量が0だったら、音楽再生音量を0にするという処理を入れました。
ということで、ソースコード。
この実装は、android.app.Applicationクラスのサブクラスとして、onCreate時に呼び出しています。
// Audio Managerを取得
AudioManager mAudio = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
// 着信の音量を取得
int vol = mAudio.getStreamVolume(AudioManager.STREAM_RING);
// 着信の音量が0だったら
if ( vol == 0 ) {
// 音楽の再生音量を同じく0に。
mAudio.setStreamVolume(AudioManager.STREAM_MUSIC, vol, AudioManager.FLAG_SHOW_UI);
}
2010年10月29日金曜日
RingerVolume と Media Volume のコントロール
悩みました。
本体の音量コントロールキーでは、
android.media.MediaPlayerで再生している場合は、
MediaVolume が操作されるのですが、
止まっている間や、android.media.MediaPlayerで再生していない場合は、Ringer Volumeが操作されます。
で、これをすべて「Media Volume」に寄せたかったのですが、寄せ方がわかりませんでした。
どうやら、Activityの onCreate 内で以下のおまじないを実行すると、
画面表示中に、ずっと「Media Volume」が操作対象となります。
setVolumeControlStream(AudioManager.STREAM_MUSIC);
やっと探しました。
本体の音量コントロールキーでは、
android.media.MediaPlayerで再生している場合は、
MediaVolume が操作されるのですが、
止まっている間や、android.media.MediaPlayerで再生していない場合は、Ringer Volumeが操作されます。
で、これをすべて「Media Volume」に寄せたかったのですが、寄せ方がわかりませんでした。
どうやら、Activityの onCreate 内で以下のおまじないを実行すると、
画面表示中に、ずっと「Media Volume」が操作対象となります。
setVolumeControlStream(AudioManager.STREAM_MUSIC);
やっと探しました。
2010年10月26日火曜日
Android アプリで設定音量を取得&再生音量に設定する。
アプリでシステムの着信音量設定を取得して、効果音をその設定音量に合わせるには、以下のとおり。
使用パッケージはandroid.media.AudioManagerとandroid.media.SoundPool。
soundpool.playと同時に音量を設定することもできるし、事前にsoundpool.setVolumeすることもできる。
使用パッケージはandroid.media.AudioManagerとandroid.media.SoundPool。
soundpool.playと同時に音量を設定することもできるし、事前にsoundpool.setVolumeすることもできる。
package jp.mediba.android.testapp;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;
public class Out extends Activity {
SoundPool soundPool;
int[] sounds = new int[1];
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.out);
int[] sounds = new int[1];
SoundPool soundPool;
soundPool = new SoundPool(1, AudioManager.STREAM_RING, 0);
sounds[0] = soundPool.load(this, R.raw.omikuji_bar, 1);
AudioManager audio = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int ringVol = audio.getStreamVolume(AudioManager.STREAM_RING);
soundPool.play(sounds[0], (float)ringVol, (float)ringVol, 0, 0, 1.0F);
}
}
2010年10月19日火曜日
XCodeとInterfaceBuilderで10分でモックアプリを作る方法(2)
全部で5回の予定です。
おそらく5回書き終わってからでないとあまり意味のない記事になっちゃいました…。
でも頑張ります。
プロジェクトの作成
View-Basedの一番シンプルなアプリをテンプレートから作成します。
これでiPhoneアプリをまず一つ作成します。

プロジェクトを保存し、シミュレーターを使って起動してみると、
Viewがひとつだけあるグレーの画面がひとつだけあるアプリが出来ます。
とりあえずの動作確認は、緑色の<ビルドと実行>をおすと、シミュレーターで確認できます。
NavigationTestViewController.xib が、このアプリの最初のViewです。
これを上の画面遷移の、「タイトル」とします。
部品を埋めていきます。
画面遷移にはボタンを使うことにします。
NavigationTestViewController.xibをダブルクリックするとInterfaceBuilderが立ち上がります。
これに遷移用のボタンを3つ作成してください。
ボタンをDrag & Drop 出来上がったボタンに分かりやすいように名前をつけました。
これを他の画面についても繰り返していきます。
画面の部品配置用のファイルを追加して、からボタンを配置していきます。
タイトル画面:NavigationTestViewController.xib
メイン画面:MainViewController.xib
結果画面:ResultViewController.xib
ヘルプ画面:HelpViewController.xib
設定画面:HelpViewController.xib
こんな感じ。
nibファイルの作成
View-Controllerのsubclass
メイン画面:MainViewController.xib
をダブルクリックして、IBを立ち上げボタンを配置します。
メイン画面なので、「結果に進む」だけのボタンだけ配置します。
(戻れないけどまあいいかと。)
というかんじで、以下の3つについても、命名規則をあわせて、同じ手順で作ります。
結果画面:ResultViewController.xib
ヘルプ画面:HelpViewController.xib
設定画面:SettingViewController.xib
全部作り終わると、画面ファイルはこんな感じです。
この状態で、GUIの準備はできました。
あとは、それぞれのボタンと、動作Actionを関連付けていきます。
ここからは、しばらくInterfaceBuilderの作業になります。
一度、すべてのxibファイルを閉じて、タイトル画面である、NavigationTestViewController.xibをダブルクリックして、表示します。
このファイルに「ボタンを押すと別画面に遷移する」という動作を関連付けましょう。
ここから出てくるファイルは、以下の3つです。
NavigationTestViewController.xib これは InterfaceBuilderでゴニョゴニョするだけ。
NavigationTestViewController.m これには、methodを追加します。
NavigationTestViewController.h これには、methodの定義だけを追加します。
じゃっそういうことでこれは明日やりますか。
登録:
投稿 (Atom)




























