[Android] OutOfMemory対処(画像サイズの変更)

Out of Memoryが連発したので対処のためやってみた。

色々試したけどサイズ変更が一番安定しました。
※今回はサーバから呼び出した画像を使用するのでマルチスレッドでの実装を前提としてます。

*****全体ソース*****

try {
        Bitmap get_image;
        URL url = new URL(【"ファイル参照先"】);
        // ファイルの読み込み
        InputStream is = url.openStream();
        
        BitmapFactory.Options options = new BitmapFactory.Options();
        // ステータス情報のみ読み込むようにする
        options.inJustDecodeBounds = true;
	
        // ステータス情報を取得(ここでは画像は読み込まない)
        BitmapFactory.decodeStream(is, null, options);
        is.close();

        // 変更サイズ計算
        options.inSampleSize = ImageResize(options, 512, 384);

        // 画像を読み込めるようにする
        options.inJustDecodeBounds = false;
        is = url.openStream();

        // 画像を取得
        get_image = BitmapFactory.decodeStream(is, null, options);
        is.close();
} catch (Exception e) {
        // TODO 自動生成された catch ブロック
        e.printStackTrace();
}

*****画像のリサイズを決めるメソッド*****

public static int ImageResize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {
        if (width > height) {
            inSampleSize = Math.round((float)height / (float)reqHeight);
        } else {
            inSampleSize = Math.round((float)width / (float)reqWidth);
        }
    }
    return inSampleSize;
}	

詳しくはWebで!←
今回はソースだけ載せときます(´・ω・)
参考にさせて頂いたサイト様も後で追加させて頂きますので!

リサイズして読み込む処理は以上です。

これだけで今回は安定しましたが、念のためにメモリ解放処理も付けておくとさらに安心できるでしょう。

Posted in Android, Java, プログラミング関連, 備忘録 | Tagged | Leave a comment

[Android] ブラウザからアプリ起動

ブラウザのリンクをクリックすると特定のアプリが起動する というもの。

まずはHTML側のページを作成

<a href="[scheme]://[host]/[path]?[query]">アプリを起動</a>

この一文でOK
各項目の意味は以下

  • scheme:起動するアプリを判別 ※後述に詳細
  • host:適当に記述←
  • path:値を受け渡すときに必要なキー ※無くても大丈夫
  • query:値を取得するKeyとValueを書く ※無くても大丈夫

試しにちゃんと書いてみるとこんな感じになる↓

<a href="myapp://jp.app/openwith?name=テスト&age=26">アプリを起動</a>

次にAndroid側
まずAndroidManifest.xmlに以下を追加。(起動するActivityに付与)
※必須

            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="myapp" android:host="jp.app" android:pathPrefix="/openwith"/>
            </intent-filter>

HTML側で記述したものは<data …/>に入る形になる。
この中で必須なのはscheneのみで、その他は無くてもアプリは起動できるようです。

ここで注意事項として、intent-filterの内部では【android.intent.action.MAIN】と【android.intent.category.LAUNCHER】の二つを今回追加するものと混合してはいけないようです。
なのでもし一緒のActivityに入れる場合は以下のようにして下さい。

            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="myapp" android:host="jp.app" android:pathPrefix="/openwith"/>
            </intent-filter>

こうすれば問題ありません。

次に値の取得
起動するActivityのお好きなタイミングに以下を追加。

		Intent i_getvalue = getIntent();
		String action = i_getvalue.getAction();
		
		if(Intent.ACTION_VIEW.equals(action)){
			Uri uri = i_getvalue.getData();
			if(uri != null){
				String name = uri.getQueryParameter("name");
				String age= uri.getQueryParameter("age");
			}
		}

以上で値が取得できます。

使いどころがあんまり無いかもしれないけど、今回使う必要があったのでメモしてみました(´,,・ω・,,`)

Posted in Android, Java, プログラミング関連, 備忘録 | Tagged | Leave a comment

[Android] HTTP POSTを使用したファイルアップロード

Android端末のファイルをサーバーにアップロードします。

今回はクライアント側だけでなくサーバー側も必要になります。

準備するものとしては
◎サーバー側
 ・POSTされたファイルを受け取るスクリプト
  これはPOSTを受け取れるのであればPHPでもJavaでも大丈夫みたいです。
  ※私はPHPで作りました。
◎クライアント側
 ・アプリケーション
 ・指定のアーカイブファイル(jarファイル)

多分これだけです←

まずクライアント側から

1.jarファイルの読み込み
http://hc.apache.org/downloads.cgiへアクセスして【HttpClient (GA)】欄から最新のバージョンをダウンロードします。※2012/10/04では最新は4.2.1です。
・ダウンロードが終わったら展開してlibフォルダから『httpclient-4.2.1.jar』と『httpmime.4.2.1.jar』を取り出します。
・アプリ側でプロジェクト直下にlibsフォルダを作成して、そこに先ほど取り出した2つのjarファイルを入れます。
・プロジェクトのプロパティー→Javaのビルド・パス→ライブラリー→Jar追加 から二つのjarファイルを追加します。
・ライブラリーの隣にある順序およびエクスポートに移りインポートしたファイルにチェックします。

これで読み込みは完了です。

2.ソースコード生成

try {
	HttpClient httpClient = new DefaultHttpClient();
	// ポスト先のファイルを指定
	HttpPost httpPost = new HttpPost(【サーバーサイドスクリプトのURL】);
	ResponseHandler<String> responseHandler = new BasicResponseHandler();
	MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
  	
	// ファイル名&パスを指定
	File file = new File(【ファイル名】);
	FileBody fileBody = new FileBody(file);
	// KEYとファイルを指定
	multipartEntity.addPart("upfile", fileBody);
    
	httpPost.setEntity(multipartEntity);
	httpClient.execute(httpPost, responseHandler);
} catch (ClientProtocolException e) {
	e.printStackTrace();
} catch (IOException e) {
	e.printStackTrace();
}

※サーバー側へのアクセスはURLをそのまま記述。
※Android端末からアップロードするファイル名はフルパスで記述すれば確実です。
メソッドの説明は面倒なので省きます。

ソースはこれでOKですが、ですが!
これをメインタスク(Activityに直接)書いてしまうとエラーになります。
ネットワーク通信系のものはいつ終わるか分からないので別タスクで動かす必要があります。
なので前に書いたインターネット上の画像を表示する(Android4.0)を参照、応用してマルチタスクにしてください。
これでソースは完了です。

3.サーバー側スクリプト

$target_dir  = "【アップロードディレクトリ】";
$target_path = $target_dir . basename( $_FILES['【POST_KEY】']['name']);
if(move_uploaded_file($_FILES['【POST_KEY】']['tmp_name'], $target_path)) {
 	echo "The file ".  basename( $_FILES['【POST_KEY】']['name'])." has been uploaded";
} else{
	echo "エラーが発生しました。";
}

簡単に言うと受け取って、指定のディレクトリへ放り投げてます。←

一応これで完成です。
AndroidManifest.xmlのネットワーク通信許可を忘れずにしてくださいね。

参考サイト
HTTP POST によるファイルのアップロード

Posted in Android, Java, プログラミング関連, 備忘録 | Tagged | 1 Comment

[Android] ネットワーク経由でadb接続

脳神経外科で頭痛診断してもらったら2つの偏頭痛持ちだったぉ・・・orz
まぁそれは置いといて。

ネットワーク経由のadb接続を試したら面白かった+便利だったのでメモ

手順
1.USBケーブルで同一ネットワークに接続しているPCとAndroid端末を接続する
※デバッグモード必須

2.コマンドを入力

adb tcpip [ポート番号]

ポート番号は任意の番号を指定する
正常に完了すれば【restarting in TCP mode port: [ポート番号]】
という返答がきます

3.USB接続を解除してWifiに接続する

4.コマンドを入力

adb connect [IPアドレス]:[ポート番号]

IPアドレスはAndroid端末のIPを確認してください
ポート番号は2で指定した番号です
接続できれば【connected to [IPアドレス]:[ポート番号]】が返ってきます
接続できなかった場合【unable to connect to [IPアドレス]:[ポート番号]:[ポート番号]】が返ってきます

以上で接続は完了です
後は通常通りadbコマンドを使用すればUSB接続無しでもちゃんと動作してくれます

ポート指定は端末を再起動するまで有効です
ポート指定している間はUSBデバッグが無効になるようなので気をつけてください
※再起動以外にもコマンドで【adb usb】と入力すればネットワーク接続を解除してUSBデバッグモードに切り替わります
この時にAndroid端末とPCがadb connectしている状態にしててください
もしconnectされていなければ何回コマンドを実行しても解除できませんので…

最後に、端末によっては接続できないものもあるようです(´・ω・)
(root権限があれば可?)
htc Jでは問題なく出来ました

では~(*・ω・)ノシ

Posted in Android, Java, プログラミング関連, 備忘録 | Tagged | Leave a comment

[Android] インターネット上の画像を表示する(Android4.0)

Android 2.3.3では動いてたコードが4.0で動かなかったので調べたら
4.x系から?外部画像(ネット上)を取得するには実行中のタスクとは別のタスクでやらないといけないらしい・・・

そこで今まで使ってたAsyncTaskを使おうとしたらこんな記事が
時代は AsyncTask より AsyncTaskLoader

なるほど、古い人間ですいませんorz

てことで新しい人間になってみました

まずは別タスクの処理をするクラスを作成

public class AppLoader extends AsyncTaskLoader<List<Bitmap>> 
{
    private final String[] urlStr;	// 画像のURL
    private List<Bitmap> bm;	// 出力用の宣言
	
    /**
     * コンストラクタ
     * 
     * @param context
     * @param imageArray
     */
    public AppLoader(Context context, String[] imageArray) {
        super(context);
        this.urlStr = imageArray;
    }
	
    /**
     * バックグラウンド処理を行う
     */
    @Override
    public List<Bitmap> loadInBackground() {
        bm = new ArrayList<Bitmap>();
        try {
            for(int i=0;i<urlStr.length ;++i){
                URL url = new URL(urlStr[i]);
                InputStream is = url.openStream();
                bm.add(BitmapFactory.decodeStream(is));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bm;
    }
}

これは最低限必要なメソッドのみを書いてるのでもっと拡張させることが出来ます

次にメインスレッドのActivity

//                                                               ※1
public class AsyncTaskLoaderActivity extends Activity implements LoaderCallbacks<List<Bitmap>> {
    private Context ctx;
    private ImageView Demo_Image01;
	
    /** テスト用画像 */
    private String image_uri[] = {"http://www.srv-shinra.com/d_Create/image/index.jpg"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.task_main);
        setTitle(this.getClass().getSimpleName());
 
        // Contextを指定
        ctx = AsyncTaskLoaderActivity.this;
        
        // レイアウト宣言
        Demo_Image01 = (ImageView)findViewById(R.id.demo_image01);
        
        // ※2
        // Activity復帰時のコールバック登録のため、必ず呼び出す
        // これが無いと動作しません
        getLoaderManager().initLoader(0, null, this);
    }

    // ※3
    // 最初に呼ばれるメソッド
    @Override
    public Loader<List<Bitmap>> onCreateLoader(int id, Bundle args) {
        AppLoader appLoader = new AppLoader(ctx,image_uri);

        appLoader.forceLoad();
        return appLoader;
    }

    // ※4
    // バックグラウンド処理が終わってから呼ばれるメソッド
    // 引数がloadInBackgroundメソッドの返り値となっている
    @Override
    public void onLoadFinished(Loader<List<Bitmap>> arg0, List<Bitmap> arg1) {
        for(int i=0; i<arg1.size(); ++i){
        	Demo_Image01.setImageBitmap(arg1.get(i));
        }
    }

    // 今回は使用しない
    @Override
    public void onLoaderReset(Loader<List<Bitmap>> arg0) {
		
    }
}

1.まずimplementsでLoaderCallbacksを実装
※今回はBitMapにしてますが各自必要なものを入れてください

2.getLoaderManager().initLoader(0, null, this)を実行
これが無いと始まりません
第一引数は0を入れていますがここは『0番のタスクが生成されているか』を確認するのですでに0がある場合処理を行いません
なので状況によって可変する必要がある場合は変数を入れて可変にするなりして対応してください

3.別タスクの処理をするクラスを呼び出す
この時引数に画像のURLを付与する
付与したURLを元に画像を引っ張ってきます

4.取得した画像データを出力する
あとは取得したデータをImageViewやらImageButtonやらに出力するだけです

これで一応問題は解決しましたー

Posted in Android, Java, プログラミング関連, 備忘録 | Tagged , | Leave a comment

[Android] アプリのインストールチェック

アプリが端末へインストールされているか確認する

参考サイト
判定関数

static final String PACKAGE_NAME = "<パッケージ名>";
static final String TARGET_APP = "<クラス名を含めたパッケージ名>";

boolean existsVisualTextClipper() {
      boolean result = false;
      List<ResolveInfo> installedAppList = new ArrayList<ResolveInfo>();
      // メインアプリケーションインテント
      Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
      mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
      // パッケージマネージャからインストール済みメインアプリリストを取得
      installedAppList = getPackageManager().queryIntentActivities(mainIntent, 0);
      for (ResolveInfo info : installedAppList) {
         ActivityInfo activityInfo = info.activityInfo;
         if (activityInfo.packageName.equals(PACKAGE_NAME)) {
           result = true;
           break;
         }
      }
      return result;
}

私が必要な箇所だけ抜き取っただけです、すいません(´・ω・)

作成した関数を使ってインストール済みか判断する

flg_app_check = existsVisualTextClipper(PACKAGE_NAME);
if(flg_app_check){
	Intent i_app= new  Intent(Intent.ACTION_MAIN);
	i_app.setClassName(PACKAGE_NAME, TARGET_APP); 
	i_app.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
	startActivity(i_app);
}
else{
	new AlertDialog.Builder(<クラス名>.this)
	.setTitle("アプリがありません")
	.setMessage("GooglePlayストアへ移動します\nよろしいですか?")
	.setPositiveButton("ストアへ移動", new DialogInterface.OnClickListener() {
		public void onClick(DialogInterface dialog, int whichButton) {
			Uri uri = Uri.parse("market://details?id=<アプリのパッケージ名>");
			Intent marketIntent = new Intent(Intent.ACTION_VIEW, uri);
			startActivity(marketIntent);
		}
	})
	.setNegativeButton("アプリへ戻る", new DialogInterface.OnClickListener() {
		public void onClick(DialogInterface dialog, int whichButton) {
			dialog.cancel();
		}
	})
	.show();
}

今回はダイアログで通知しました
通知方法は各々で設定しちゃってください

アプリがある場合は何事も無く遷移しますが
アプリが存在しない場合GooglePlayストアへ移動するように通知させました
※遷移先のアプリがストアに存在している事

Posted in Android, Java, プログラミング関連, 備忘録 | Tagged | Leave a comment

[Android] adbコマンド

ADBコマンドに関するメモ

・デバイスの確認
adb devices

・ログを出力
adb logcat
(※Ctrl+Cで抜けます)

・アプリ(apkファイル)を端末へインストール
⇒adb install <apkファイル名>.apk
(※ディレクトリを移動してない場合はフルパスで記述)
・デバイスが複数ある場合
⇒adb -s <端末名> install <apkファイル名>.apk

・アプリ(apkファイル)をアップデート
⇒adb install -r <apkファイル名>.apk
(※ディレクトリを移動してない場合はフルパスで記述)

・アプリをアンインストール
⇒adb uninstall <アプリのパッケージ名>

アンインストールだけはapkファイル名ではなくパッケージ名を入力しないといけないとか面倒・・・

・ネットワーク経由でadbコマンドを実行
こちらへ

Posted in Android, Java, プログラミング関連, 備忘録 | Tagged | Leave a comment

[Android] 横線を引く

忘れてたのでメモ。

横に1本線を引く方法

<TextView 
android:id="@+id/Widthline"
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#FFFFFF">
</TextView>

これだけ!

Posted in Android, Java, プログラミング関連, 備忘録 | Tagged | Leave a comment

[Android] VerifyError

たまに起こる『java.long.VerifyError』について

これが起こるのは大きく分けて2つ
1.AndroidSDKのバージョンの問題
2.外部ライブラリの問題

1つ目のAndroidSDKも問題は以下のような場合
・Manifestファイルでtargetを10(android 2.3.3)、minSdkVersionを4(android1.6)で開発する
・android2.3.3以降で使用できる機能を実装
・android2.3.3で実行⇒正常起動
・android1.6で実行 ⇒異常終了(VerifyError発生)

このようにAndroidSDKのバージョンの違いで使用できないものを使おうとするとVerifyErrorが発生する

次に外部ライブラリの場合
・推奨環境がAndroid4.0以上の外部ライブラリを導入
・targetを10(android 2.3.3)に設定
・Android2.3.3で実行⇒異常終了(VerifyError発生)

Android4.0以上が保持する機能を使用するライブラリなのでもちろん落ちます

しかし、これ以外にも落ちる場合が。。。(こっちが見つけるの面倒

推奨環境もtargetも実行端末も問題がない場合でも落ちるときがあります

この場合はビルド・パスに問題がある可能性が高いです

プロジェクトのプロパティ

Javaのビルド・パス

ライブラリ(外部ライブラリが追加されていることを確認)

順序およびエクスポート ※ここが重要

最後の重要ポイントにて使用するライブラリにチェックが入っているかを確認してください

もしチェックが外れていればチェックを付けて更新してください

更新したらプロジェクトをクリーン・リビルドをかけて再実行

これで私は回避できました

Posted in Android, Java, プログラミング関連, 備忘録 | Tagged , | Leave a comment

[Java,Android] 証明書の作り方

Androidアプリを制作していて特に気にしてなかったkeystore関連で躓いたのでメモ

Eclipseのツールで作成したkeystoreから証明書を発行する

1.keystoreファイルのディレクトリを確認
2.~/Java/jdk1.x.x~/binへパッチが通ってることを確認
(通ってなければシステム詳細設定→環境変数から通す)
3.以下コマンド処理

・証明書の確認

// keystore_name と password_code は任意の文字
// ※keystoreはフルパスで記述
keytool -list -v -keystore keystore_name -storepass password_code

・確認できたら証明書を取得

// keystore と alias-name と file-name は任意の文字
// ※keystoreはフルパスで記述
keytool -exportcert -keystore keystore_name -alias alias-name -file file-name.def

今回はDEF形式で保存しています。

以上ですー

Posted in プログラミング関連 | Tagged , | Leave a comment