2013年2月21日木曜日

実行エラー(at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:240))

実行時のエラー
 at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:240)


これが出たときは、 manifest.xmlの パッケージ名が起動するActivityのパッケージ名と相違がある時に出現します。

manifest.xmlは慎重に作成しましょう!!


xmlで変数を管理-01(getResources(), getString, getInteger)


res/valueの中にxmlを作成すると、
configファイル感覚で変数を管理できます。

ソース内やレイアウトファイル、マニフェストファイルでも
共通で使えるので、覚えておいて損はないと思います。

今回はプロジェクト作成すると、
存在するstringsのファイル名を直刺ししていますが、
上記に記したように、valueフォルダにxmlファイルを作成すれば完成します。

■文字列型の取得
valueのstrings.xmlに下記を追記
<string name="test_string">Hello, World!!</string>

javaファイル
String sText = getResources().getString(R.string.test_string);

getResources()で自分のリソースを確認して、
string型で取得するのでgetString

R.はresフォルダーのR。←本当かあ!!

string型で宣言されているtest_string
を取得

■数字型の取得
valueのstrings.xmlに下記を追記
<integer name="test_integer">97</integer>
javaファイル
int iInt     = getResources().getInteger(R.integer.test_integer);
String sInt     = getResources().getString(R.integer.test_integer);

int型で取得するならgetIntege、
String型で取得するならgetString
と選べます。

■フォーマッター
valueのstrings.xmlに下記を追記
<string name="test_formater_s">Hi! %s</string>

javaファイル
String sText = getResources().getString(R.string.test_formater_s, "Mike");

フォーマッター(Formatter)について詳細はこちらを参照

http://developer.android.com/intl/ja/reference/java/util/Formatter.html
簡単にザックリいうと、%sとか%dがカンマ区切りの文字に置換されるということです。


■サンプルソース
・java

package com.example.Package;

import android.os.Bundle;
import android.app.Activity;

import android.graphics.Color;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//レイアウトの作成
LinearLayout oLayout = new LinearLayout(getApplicationContext());
//レイアウトにパーツを上から順に設置する設定
oLayout.setOrientation(LinearLayout.VERTICAL);
//文字を見やすくするために背景を黒色に
oLayout.setBackgroundColor(Color.BLACK);
//レイアウトの設定
setContentView(oLayout);

//レイアウトパラム定数(縦横の長さの定数)の格納
       int WC = ViewGroup.LayoutParams.WRAP_CONTENT;
       int MP = ViewGroup.LayoutParams.MATCH_PARENT;
//レイアウトの横幅・縦幅を設定
LayoutParams oLayPar = new LinearLayout.LayoutParams(MP, 40);
String sText = getResources().getString(R.string.test_string);
int sInt     = getResources().getInteger(R.integer.test_integer);
       String sText2= getResources().getString(R.string.test_formater_s, "Mike");
  String sText3= getResources().getString(R.string.test_formater_i, 3);
       String sText4= getResources().getString(R.string.test_formater_ss, "Mike", "pen");
  String sText5= getResources().getString(R.string.test_formater_si, "Mike", 2);
//テキストビューを作成して、取得した情報を出力
oLayout.addView(make_TextView(sText), oLayPar);
oLayout.addView(make_TextView(sInt), oLayPar);
oLayout.addView(make_TextView(sText2), oLayPar);
oLayout.addView(make_TextView(sText3), oLayPar);
oLayout.addView(make_TextView(sText4), oLayPar);
oLayout.addView(make_TextView(sText5), oLayPar);
    }

  //テキストビューの作成
    private TextView make_TextView(String sMessage){
  //テキストビューの生成
  TextView tv = new TextView(getApplicationContext());
  //メッセージの設定
  tv.setText(sMessage);
  return tv;
  }

  //テキストビューの作成(long型用)
  private TextView make_TextView(long sMessage){
  return make_TextView(String.valueOf(sMessage));
  }

  //テキストビューの作成(int型用)
  private TextView make_TextView(int sMessage){
  return make_TextView(String.valueOf(sMessage));
  }
}

・strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="test_string">Hello, World!!</string>
    <integer name="test_integer">97</integer>
    <string name="test_formater_s">Hi! %s</string>
    <string name="test_formater_i">%d個</string>
    <string name="test_formater_ss">Hi! %1$s. Do you Have a %2$s ?</string>
    <string name="test_formater_si">%1$Sは%2$d本のペンを持っています。</string>
</resources>

■実行結果





<string name="test_formater_ss">Hi! %1$s. Do you Have a %2$s ?</string>
フォーマッタの%1$sは第一引数に置換されますという意味で、%2$sは第2引数に
置換されちゃうという意味です。
また、%sを%Sと大文字にすると、今まで小さかったmikeが大きく成長します。MIKEに。

2013年2月20日水曜日

GooglePlayのランキング-01


人気のあるAndroidアプリにするために
必要なのが、プロモーション活動ですね。

プロモーションにもいろいろありますが、
効率的なのが単純にGooglePlayのランキング上位
にアプリが掲載されることです。

Webと同じで、上に表示されればされるほど、
インストール数は増えます。

インストール数が増えれば、さらにランキングが上昇するという好循環!!

ただ、ランキングの選出基準が単純にインストール数だけでなく、
レビューやアクティブ率を見ているとかいう情報もあるので、
一概には言えませんが、インストール数の増加は
ランキング上昇のためには重要なファクターの一つではあります。

ではなぜ、GooglePlayのランキング上位が効率的なプロモーション活動かというと。

いつも目的意識を高くもっている人は
インストールしたいアプリを検索から、綺麗に一本釣りするかもしれません。
しかし、目的意識の低いプラプラしている人は
「暇だし、やることないし、何かアプリでもインストールしよう。」
と、適当に各カテゴリーに入って、適当にアプリを探します。
みーちゃんはーちゃんな人は
「とりあえず人気のアプリは試してみよう」
と、各カテゴリーのランキング上位のアプリを片っ端にインストールします。

皆が目的意識を高くもつ、豊かな国にいつかなるといいですね。


ではでは、ランキング上位に掲載されるために


1.新着ランキングを狙おう!!
アプリを公開してから、1ヶ月以内は新着ランキングに掲載されます。
新着ランキングは比較的簡単に上位に掲載されますし、ユーザーからのインストール数も多いです。

2.人気のないカテゴリーを選ぼう!!
特にゲームランキングのアーケードアクションはランキングの群雄割拠のバルカン半島です。
それなら、カテゴリーゲームのスポーツやレースにする方が全然ランキング上位に掲載されます。
また、思い切ってアプリケーションのエンターテイメントにするとかもありです。
「人気のないカテゴリーじゃ、意味なくない?」
と思われるかもしれませんが、ランキングに表示されなかったらアプリ公開時にカテゴリーを選んだ意味がありません。
もう一度いいますと、ランキングに表示されなければカテゴリーなんて、何の意味も持ちません。(Googleに統計情報を渡すだけ)

3.GoogleWallet課金機能の導入!!
GoogleWalletの課金機能を実装すると、売上ランキングにも表示されます。
また、個人的な感想ですが課金機能を実装しているだけで、ランキング上昇しやすくなります。本当か?


上記の3つが簡単にできるランキング対策です。

1の新着ランキングを狙いは結構大事です。
新着ランキングの上位はユーザーからのインストール数がかなり増えます。
人間は質よりもフレッシュな物を求めているということです。

また、新着ランキング時に順位を稼いでおくと
その勢いのまま、カテゴリーランキング上位をキープできます。
逆を言うと、ここで下位にいますと、これからのランキング上昇には相当なお金が必要となります。
天下分け目の1ヶ月と言えますね。

なので、アプリをリリースする際には慎重に慎重に検証に検証を重ねてからの
リリースが望ましいと思います。

また、最近ではランキングを上昇させるための会社も増えてきています。



これからもプラプラといろいろなアプリをインストールして、
使える技術やプロモーションを盗んでいきたいと思います。

パッケージ情報の取得(PackageInfo, getPackageManager())

アプリのバージョン情報には2種類ありまして、

android:versionCode="1"

VersionCodeはGooglePlayに公開する際に使われます。
アプリの更新をする際には、1度公開したバージョンよりも
大きい数字を指定しないと更新できません。
また、この数字はユーザーには公開されません。

android:versionName="1.0"

VersionNameはGooglePlayや端末インストール後に
ユーザーが確認できるバージョンです。
アプリの更新時に必ず更新しないといけないわけではありません。
わりと自由に指定できます。

android:versionName="1.0.2"

とかもOKです。

VersionCodeはGoogle管理用
VersionNameは制作者管理用

という認識で問題ないかと思われます。

VersionNameは既にインストール済のユーザーに
最新版のアプリをインストールしてもらうために使えます。
バグが見つかった時とか。。

個人的にはサーバー側でアップデートさせるバージョンを管理して、
そのバージョンよりも、低かったら強制バージョンアップなアプリを作っています。

ではでは、

アプリのバージョン情報、最終更新日、最初にインストールした日付の取得してみましょう。



サンプル文はこんな感じです。

■サンプル
package com.example.Package;

import android.os.Bundle;
import android.app.Activity;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Color;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //レイアウトの作成
        LinearLayout oLayout = new LinearLayout(getApplicationContext());
        //レイアウトにパーツを上から順に設置する設定
        oLayout.setOrientation(LinearLayout.VERTICAL);
        //文字を見やすくするために背景を黒色に
        oLayout.setBackgroundColor(Color.BLACK);
        //レイアウトの設定
        setContentView(oLayout);
  
        //レイアウトパラム定数(縦横の長さの定数)の格納
        int WC = ViewGroup.LayoutParams.WRAP_CONTENT;
        int MP = ViewGroup.LayoutParams.MATCH_PARENT;
        //レイアウトの横幅・縦幅を設定
        LayoutParams oLayPar = new LinearLayout.LayoutParams(MP, 40);
    
        try {
            //PackageInfoの取得
            PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_META_DATA);
            //パッケージのバージョンネームの取得
            String versionName    = packageInfo.versionName;
            //パッケージのバージョンコードの取得
            int versionCode       = packageInfo.versionCode;
            //最初にインストールした日付
            long firstInstallTime = packageInfo.firstInstallTime;
            //最後にインストールした日付
            long lastUpdateTime   = packageInfo.lastUpdateTime;
            //他のアプリと共有する場合のLinuxID
            String sharedUserId   = packageInfo.sharedUserId;
 
            //テキストビューを作成して、取得した情報を出力
            oLayout.addView(make_TextView("versionName = " + versionName), oLayPar);
            oLayout.addView(make_TextView("versionCode = " + versionCode), oLayPar);
            oLayout.addView(make_TextView("firstInstallTime = " + firstInstallTime), oLayPar);
            oLayout.addView(make_TextView("lastUpdateTime = " + lastUpdateTime), oLayPar);
            oLayout.addView(make_TextView("sharedUserId = " + sharedUserId), oLayPar);

        } catch (NameNotFoundException e) {
            //TODO 自動生成された catch ブロック
            e.printStackTrace();
        }
    }
 
    //テキストビューの作成
    private TextView make_TextView(String sMessage){
        //テキストビューの生成
        TextView tv = new TextView(getApplicationContext());
        //メッセージの設定
        tv.setText(sMessage);
        return tv;
    }

    //テキストビューの作成(long型用)
    private TextView make_TextView(long sMessage){
        return make_TextView(String.valueOf(sMessage));
    }
 
    //テキストビューの作成(int型用)
    private TextView make_TextView(int sMessage){
        return make_TextView(String.valueOf(sMessage));
    }
}
実行結果


このような感じになりました。

manifest.xmlと見比べて、正しいかの判定をお願いいたします。

Time系がよくわからない数字となっていますが、
これはUTCの表示のため。こうなっております。
1970年の1月1日から、どれだけ時間が経過しているかで、
時刻を管理しています。


oLayout.addView(make_TextView("firstInstallTime = " + new Date(firstInstallTime)), oLayPar);
oLayout.addView(make_TextView("lastUpdateTime = " + new Date(lastUpdateTime)), oLayPar);

Date型で囲めば


こんな感じで、先ほどよりもわかりやすくなったと思います。

2013年2月13日水曜日

Android目次

機能

バイブ機能(Vibrator)

アプリの保存先(installLocation)

アプリ内の情報を保存する(PreferenceManager, SharedPreferences)...

ダイアログの表示(shwDialog, CreateDialog)

選択型ダイアログ(setSingleChoiceItems)

ダイアログで複数のエディットテキストを表示したい!!(EditText)


パッケージ情報の取得(PackageInfo, getPackageManager())

BGMの再生(MediaPlayer)

アラートダイアログにレイアウトを読み込ませる(AlertDialog, inflate)

端末識別コード(TelephonyManager, TELEPHONY_SERVICE)

JSON( JSONObject, rootObject)

タッチを検出(onTouchEvent, MotionEvent)

アプリ内課金実装(IInAppBillingService.aidl, IabException)

ローカルファイルの読み込み(getAssets(), BufferedReader)

ローカルのHTMLファイルを表示(ローカルファイル,file:///android_asset)

ファイルの書き込み、生成(FileOutputStream, file:///data/data/)...

Activity系

文字を表示させる(TextView)

Activityを呼ぶ(intent, startActivity)

Activityの引数(setResult, onActivityResult)

起動時のActivityを変更する

終了処理(finish)

レイアウトを非表示に(setVisibility(View.GONE), findViewById)...

ドロップダウンの表示(AutoCompleteTextView)

ラジオボタン-01(RadioGroup, RadioButton)

ラジオボタン-02(カスタマイズ編)

グリッドデザイン(GridView,BaseAdapter)

リストビューの基礎(ListView, BaseAdapter)

ListView -02 (リストの追加、スクロールの一番下を検知、スクロールが一番下になったら追加...

ピッカー(NumberPicker)

画面遷移(ViewFlipper)

画像表示(ImageView, setScaleType)

サーバーに格納している画像を表示させる(ImageView, URL)

シークバー、 スライダー(SeekBar)

layout_weightをjavaソースで書く(android:layout_weight=)

layout_weightの設定( setLayoutParams )

ページめくり(PagerAdapt)

Webの表示-01(WebView )

Webの表示-02(WebView,requestWindowFeature(Window.FEAT...

メニューの表示(onCreateOptionsMenu())

タブの表示(ActionBar.TabListener, FragmentActivity, Tab...

エラー

画像が表示されない。OPENGL

Android 4 が使えない!!

WebViewでFLASH表示できない!!(android:hardwareAccelerated)...

実行エラー(at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:240))

エラー Android requires compiler compliance level 5.0...

実行エラーjava.lang.RuntimeException: Unable to stop ac...

エラー  android.util.AndroidRuntimeException: request...


ビルド時のAndroidバージョン変更(Project Build Target)

Contextとは(getApplicationContext(),Activity,getAppl...







起動時のActivityを変更する


すごい、基礎的な事ですが、
アプリの起動時に立ち上がるActivityを
変更する方法について。


manifest.xmlで最初に立ち上げたいActivity内に

<intent-filter>
  <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

を記述。

例)

<activity
  android:name=".subActivity"
    android:configChanges="keyboardHidden|orientation">
</activity>
<activity
  android:name=".MainWebViewActivity"
    android:screenOrientation="portrait"
    android:configChanges="keyboardHidden|orientation">
    <intent-filter>
      <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

こんな感じでいいかと思われます。


例だと、MainWebViewActivityを先に起動させる様になっております。




2013年2月10日日曜日

広告実装-02

Admob実装編!!


まずは、Admobにアカウントの作成です。
アカウントを作成して、広告SDKを入手しましょう

Admobアカウントは持っているGoogleアカウントで作成できます。
途中で納税者IDやGooglePlayのパッケージURLの入力を
求められますが、無視で大丈夫です。

無事にSDKを入手しました??
SDKとアプリの管理番号は他のアプリにも何回でも使いまわせます。
他のアプリに広告を実装する時も同じ方法でOKです。

また、実装方法に関してはZipの中に正式な実装方法が記載されているので、
それを見るのが一番かと思います。

とは言いつつ。。。。


1.libsの追加



libsフォルダ直下にGoogleAdMobAdsSdk~を格納しましょう!!

libsフォルダがなかったら、
【プロジェクト名】→【右クリック】→【新規】→【フォルダー】→【libs】
でフォルダ作成




2.ライブラリーの確認

【プロジェクト名】→【右クリック】→【ビルド・パス】→【ビルドパスの構成】





この画面で、先ほど追加したライブラリが表示されていたら、OKです。
libsフォルダ直下のライブラりーは勝手に追加されるらしいです。

追加されていない方は【jar 追加】を押して、



この画面で、先ほど追加したjarファイルを選択すれば、OKです。

3.アクティビティーに追加する


package com.example.admob;

import com.google.ads.AdRequest;
import com.google.ads.AdSize;
import com.google.ads.AdView;

import android.os.Bundle;
import android.app.Activity;
import android.view.Gravity;
import android.view.ViewGroup.LayoutParams;
import android.widget.FrameLayout;

public class MainActivity extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
      // AdMobのViewを作成 
  AdView adView = new AdView(this, AdSize.BANNER, "管理番号");
  AdRequest adRequest = new AdRequest();
  adView.loadAd(adRequest);
  FrameLayout.LayoutParams para = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        // 画面下部に表示
  para.gravity = Gravity.BOTTOM;  

  addContentView(adView, para);
    }
}

4.manifest,xmlの編集

applicationタグ内に

<activity
  android:name="com.google.ads.AdActivity"
  android:configChanges="orientation|keyboard|keyboardHidden" >
</activity>
<receiver 
  android:name="com.admob.android.ads.analytics.InstallReceiver"
  android:exported="true">
  <intent-filter>
    <action android:name="com.android.vending.INSTALL_REFERRER" />
  </intent-filter>
</receiver>


<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

広告のJarファイルのVersionと、プロジェクトのAndroidVersionによっては実装が上手くいかない
場合もありますが、その時はレシーバとかをコメントアウトすると、動いたりします。

実行すると



para.gravity = Gravity.BOTTOM;  
があるので、画面の下に表示されていますが、指定を変えれば好きな場所に広告を貼れます。
管理番号を取得して、20分くらいたたないと広告が表示されないことがありますので、申請したばっかりで、広告が表示されない方はしばし休憩を。

広告は画面の一部を占めてしまうので、企画の段階でどの場所に表示させるかを考えましょう!!


また、ビルドするAndroidのバージョンとAdmobのバージョン間で不整合が起きることがあります。

とりあえず、GoogleAdMobAdsSdk~のバージョンは4.11を使っていると今のところ大丈夫です。


2013年2月5日火曜日

POSTでエラー(CoreProtocolPNames.USE_EXPECT_CONTINUE)


一部の端末でPOSTが上手くいかない!!
プロキシーサーバーでエラーが帰ってくる!!


POSTが上手くいかない方へ~


httppost.getParams().setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, Boolean.FALSE);

を追加するとどうでしょうか??

よくわからないのですが、ExceptionHeaderというものを
空にする処理です。

追記場所はHttpPostの生成後

httppost = new HttpPost(sFilePath);
//EXceptionHeaderを空にする
httppost.getParams().setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, Boolean.FALSE);
HttpResponse response = httpclient.execute(httppost);


こんな感じで、お願いいたします。


T01-CでPOSTエラーになっていたので、
調べてみたら、このようなデフォルト処理が必要でした。。。
何もしないとよくわからないヘッダー情報がもれなくついてくるそうです。。。

他の端末で上手くいっていたのですが。。。。

端末ごとのブラウザーの違いでこのようなエラーが出るのかな??