Software/Android/アプリケーション開発テキスト/Chapter05
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
]
開始行:
[[Software/Android/アプリケーション開発テキスト]]
*Chapter 5 : サービスを利用したアプリケーションの作成 [#i...
この章ではサービスを利用して簡易RSSリーダーを拡張してい...
Chapter 4で作成した簡易RSSリーダーでは取得ボタンのタッ...
~
~
**5-1. サービスクラスの作成 [#a61c3b95]
まずはRSSReaderプロジェクトにバックグラウンドでRSSフィ...
android.app.ServiceをベースクラスとしたFeedServiceを生...
-リスト5-1 :
public class FeedService extends Service implements Runn...
private static final String SERVICE_ACTION = "com.b...
private static final String BROADCAST_MSG = "com.be...
private boolean mWorking = false;
private FeedList mListFG = null;
private FeedList mListBG = null;
~
定数SERVICE_ACTIONはこのサービスで取り扱うアクションを...
バックグラウンドでのフィード取得中に外部からリストを参...
続いてonStartメソッドを追加します(リスト5-2)。
-リスト5-2 :
@Override
public void onStart(Intent intent, int startID) {
super.onStart(intent, startID);
Thread thread = new Thread(this);
thread.run();
}
~
onStartはサービスが開始されると呼び出されるメソッドで、...
アクティビティなどのコンポーネントから直接サービスの機...
-リスト5-3 :
@Override
public IBinder onBind(Intent arg0) {
return mIFeedServiceBinder;
}
~
IBinder型のメンバ変数mIFeedServiceBinderを返すことで、...
前述の通り、このクラスにRunnableインターフェースを実装...
-リスト5-4 :
@Override
public void run() {
RSSReaderApplication app = (RSSReaderApplicati...
mListBG = new FeedList();
if (mListBG.get(app) > 0) {
lock();
mListFG = mListBG;
unlock();
Intent bcast = new Intent(BROADCAST_MSG);
getBaseContext().sendBroadcast(bcast);
}
Intent ac = new Intent(SERVICE_ACTION);
PendingIntent pi = PendingIntent.getService(th...
AlarmManager am = (AlarmManager) getSystemServ...
long at = System.currentTimeMillis() + 60000;
am.set(AlarmManager.RTC, at, pi);
}
~
runメソッドではまず、RSSReaderApplicationクラスのインス...
置き換えが終わったら定数BROADCAST_MSGをアクションに設定...
続いて定数SERVICE_ACTIONをアクションとして設定したイン...
ペンディングインテントの発行先としてこのサービスを指定...
これによりこのサービスが60秒毎に呼び出され、定期的なRSS...
サービスバインダーを追加します(リスト5-5)。IFeedServi...
-リスト5-5 :
// service binder
private final IFeedService.Stub mIFeedServiceBinder...
@Override
public void lockList() {
lock();
}
@Override
public void unlockList() {
unlock();
}
@Override
public int getFeedCount() throws RemoteExcepti...
if (mListFG != null) {
return mListFG.count();
}
return 0;
}
@Override
public int getItemType(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.g...
return list.get(index).itemType();
}
return 0;
}
@Override
public String getFeedTitle(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.g...
return list.get(index).feedTitle();
}
return "";
}
@Override
public String getArticleTitle(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.g...
return list.get(index).articleTitle();
}
return "";
}
@Override
public String getPubDate(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.g...
return list.get(index).pubDate();
}
return "";
}
@Override
public String getDescription(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.g...
return list.get(index).description();
}
return "";
}
@Override
public String getLink(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.g...
return list.get(index).link();
}
return "";
}
};
~
lockList/unlockListはRSSフィードリストを参照する際に排...
-リスト5-6 :
private synchronized void lock() {
while (mWorking) {
try {
wait();
}
catch (Exception e) {
}
}
mWorking = true;
}
private synchronized void unlock() {
mWorking = false;
}
~
最後に排他制御に使用するlock/unlockメソッドを追加します...
以上でサービスクラスの作成は完了です。引き続きAIDLファ...
Package ExplorerでRSSReaderのsrc/com.beatcraft.rssreade...
-リスト5-7 IFeedService.aidl :
package com.beatcraft.rssreader;
interface IFeedService {
void lockList();
void unlockList();
int getFeedCount();
int getItemType(int index);
String getFeedTitle(int index);
String getArticleTitle(int index);
String getPubDate(int index);
String getDescription(int index);
String getLink(int index);
}
~
作成されたIFeedService.aidlファイルを開き、リスト5-7の...
最後にRSSReaderのマニフェストファイル(AndroidManifest....
-リスト5-8 :
<service android:name=".FeedService" >
<intent-filter >
<action android:name="com.beatcraft.rssr...
</intent-filter>
</service>
~
インテントフィルタとして、サービスクラス内で定義した定...
~
~
**5-2. ブロードキャストレシーバの作成 [#d0e9ec46]
続いて、サービスが発行したブロードキャストを受信するブ...
android.content.BroadcastReceiverをベースクラスとしてFe...
-リスト5-9 FeedReceiver.java :
public class FeedReceiver extends BroadcastReceiver {
IFeedReceiver mReceiver;
public FeedReceiver(IFeedReceiver receiver) {
mReceiver = receiver;
}
@Override
public void onReceive(Context context, Intent inten...
mReceiver.feedReceived();
}
}
~
IFeedReceiverは受信したブロードキャストを実際に処理する...
続いてIFeedReceiverを作成するため、Package ExplorerでRS...
-リスト5-10 IFeedReceiver.java :
package com.beatcraft.rssreader;
public interface IFeedReceiver {
void feedReceived();
}
~
作成されたIFeedReceiver.javaを開き、feedReceivedメソッ...
以上でブロードキャストレシーバは完成です。
~
~
**5-3. サービスを利用する [#f59de66b]
サービスとブロードキャストレシーバが完成したので、ここ...
-リスト5-11 :
public class RSSReaderActivity extends ListActivity impl...
private static final String BROADCAST_MSG = "com.be...
private FeedList mList = null;
private IntentFilter mIFilter;
private IFeedService mIFeedServiceBind = null;
private ServiceConnection mServiceConnection = new ...
@Override
public void onServiceConnected(ComponentName n...
// インターフェースを取得
mIFeedServiceBind = IFeedService.Stub.asI...
}
@Override
public void onServiceDisconnected(ComponentNam...
//
}
};
~
IFeedReceiverのimplementsを追加し、ブロードキャスト受信...
引き続きITaskEntityがimplementsされていますが、これは従...
ボタンによるフィードの手動取得を廃止するため、onCreate...
-リスト5-12 :
button = (Button) findViewById(R.id.Get);
button.setOnClickListener(this);
~
-リスト5-13 :
case R.id.Get:
mList = null;
HttpAccessTask task = new HttpAccessTask(...
task.execute(this);
break;
~
続いてonCreateメソッドの最後に、ブロードキャストレシー...
-リスト5-14 :
FeedReceiver recv = new FeedReceiver(this);
mIFilter = new IntentFilter(BROADCAST_MSG);
registerReceiver(recv, mIFilter);
Intent intent = new Intent(getBaseContext(), Fee...
startService(intent);
bindService(intent, mServiceConnection, BIND_AUT...
~
先ほど実装したFeedReceiverを生成し、文字列定数BROADCAST...
FeedServiceを明示的に指定したインテントを生成し、startS...
インターフェースIFeedReceiver唯一のメソッドであるfeedRe...
-リスト5-15 :
@Override
public void feedReceived() {
ListGenerateTask task = new ListGenerateTask();
task.execute(this);
}
~
サービスがRSSフィードの取得を完了し、ブロードキャストを...
ListGenerateTaskは後ほど作成しますが、HttpAccessTask同...
修正後のbackgroundProcメソッドがリスト5-16になります。
-リスト5-16 :
@Override
public void backgroundProc() {
int count = 0;
mList = new FeedList();
if (mIFeedServiceBind != null) {
try {
mIFeedServiceBind.lockList();
count = mIFeedServiceBind.getFeedCoun...
FeedItem item;
for (int i = 0; i < count; ++i) {
int type = mIFeedServiceBind.get...
item = new FeedItem(type);
item.setFeedTitle(mIFeedServiceB...
item.setArticleTitle(mIFeedServi...
item.setPubDate(mIFeedServiceBin...
item.setDescription(mIFeedServic...
item.setLink(mIFeedServiceBind.g...
mList.getList().add(item);
}
mIFeedServiceBind.unlockList();
}
catch (RemoteException e) {
e.printStackTrace();
}
}
}
~
空のFeedListを生成したら、サービスバインダーのlockList...
ロックに成功したらフィードの数を取得し、フィード数分の...
-リスト5-17 :
@Override
public void postProc() {
if (mList.count() > 0) {
ArrayList<FeedItem> list = mList.getList();
if (list != null) {
FeedAdapter adapter = new FeedAdapte...
setListAdapter(adapter);
}
}
}
~
postProc(リスト5-17)ではバックグラウンドで生成したリ...
最後にListGenerateTaskを作成します。ベースクラスをAsync...
-リスト5-18 :
package com.beatcraft.rssreader;
import android.os.AsyncTask;
public class ListGenerateTask extends AsyncTask<ITaskEnt...
private ITaskEntity mITaskEntity;
@Override
protected Void doInBackground(ITaskEntity... params...
mITaskEntity = params[0];
mITaskEntity.backgroundProc();
return null;
}
@Override
protected void onPostExecute(Void v) {
mITaskEntity.postProc();
}
}
~
実際の処理はアクティビティに実装されたbackgroundProc/po...
以上で全ての実装は完了です。実行して動作を確認してみて...
~
~
**5-4. サービス版RSSReader全ソースコード/AIDLファイル/XML...
-リスト5-19 RSSReaderApplication.java :
package com.beatcraft.rssreader;
import android.app.Application;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
public class RSSReaderApplication extends Application {
private static final String CONF_NAME = "rssreader.c...
public static final int DEFAULT_NUM_OF_GET = 3;
public static final int NUM_OF_FEED = 10;
private int mNumOfGet = DEFAULT_NUM_OF_GET;
private String mFeedURL[];
@Override
public void onCreate() {
mFeedURL = new String[NUM_OF_FEED];
loadConfig();
}
public int numberOfGet() {
return mNumOfGet;
}
public void setNumberOfGet(int numOfGet) {
mNumOfGet = numOfGet;
}
public String feedURL(int index) {
if ((index < 0) || (10 <= index)) {
return null;
}
return mFeedURL[index];
}
public void setFeedURL(int index, String url) {
if ((index < 0) || (NUM_OF_FEED <= index)) {
return;
}
mFeedURL[index] = url;
}
public void clearFeedURL() {
for (int i = 0; i < NUM_OF_FEED; ++i) {
mFeedURL[i] = "";
}
}
public void loadConfig() {
SharedPreferences pref = getSharedPreferences(CO...
mNumOfGet = pref.getInt("NumOfGet", DEFAULT_NUM_...
for (int i = 0; i < NUM_OF_FEED; ++i) {
String key = String.format("FeedURL%02d", (i...
mFeedURL[i] = pref.getString(key, "");
}
}
public void saveConfig() {
SharedPreferences pref = getSharedPreferences(CO...
Editor pe = pref.edit();
pe.putInt("NumOfGet", mNumOfGet);
for (int i = 0; i < NUM_OF_FEED; ++i) {
String key = String.format("FeedURL%02d", (i...
pe.putString(key, mFeedURL[i]);
}
pe.commit();
}
}
~
-リスト5-20 RSSReaderActivity.java :
package com.beatcraft.rssreader;
import java.util.ArrayList;
import android.app.ListActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.Button;
public class RSSReaderActivity extends ListActivity impl...
private static final String BROADCAST_MSG = "com.bea...
private FeedList mList = null;
private IntentFilter mIFilter;
private IFeedService mIFeedServiceBind = null;
private ServiceConnection mServiceConnection = new S...
@Override
public void onServiceConnected(ComponentName nam...
// インターフェースを取得
mIFeedServiceBind = IFeedService.Stub.asInte...
}
@Override
public void onServiceDisconnected(ComponentName ...
//
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
Button button;
button = (Button) findViewById(R.id.Config);
button.setOnClickListener(this);
getListView().setOnItemClickListener(new Adapter...
@Override
public void onItemClick(AdapterView<?> paren...
FeedItem item = (FeedItem) getListView()...
Intent intent = new Intent(getApplicatio...
intent.putExtra("FeedTitle", item.feedTi...
intent.putExtra("ArticleTitle", item.art...
intent.putExtra("PubDate", item.pubDate(...
intent.putExtra("Description", item.desc...
intent.putExtra("Link", item.link());
startActivity(intent);
}
});
FeedReceiver recv = new FeedReceiver(this);
mIFilter = new IntentFilter(BROADCAST_MSG);
registerReceiver(recv, mIFilter);
Intent intent = new Intent(getBaseContext(), Fee...
startService(intent);
bindService(intent, mServiceConnection, BIND_AUT...
}
@Override
public void onClick(View view) {
int id = view.getId();
switch (id) {
case R.id.Config:
showConfig();
break;
}
}
@Override
public void feedReceived() {
ListGenerateTask task = new ListGenerateTask();
task.execute(this);
}
@Override
public void backgroundProc() {
int count = 0;
mList = new FeedList();
if (mIFeedServiceBind != null) {
try {
mIFeedServiceBind.lockList();
count = mIFeedServiceBind.getFeedCount();
FeedItem item;
for (int i = 0; i < count; ++i) {
int type = mIFeedServiceBind.getItem...
item = new FeedItem(type);
item.setFeedTitle(mIFeedServiceBind....
item.setArticleTitle(mIFeedServiceBi...
item.setPubDate(mIFeedServiceBind.ge...
item.setDescription(mIFeedServiceBin...
item.setLink(mIFeedServiceBind.getLi...
mList.getList().add(item);
}
mIFeedServiceBind.unlockList();
}
catch (RemoteException e) {
e.printStackTrace();
}
}
}
@Override
public void postProc() {
if (mList.count() > 0) {
ArrayList<FeedItem> list = mList.getList();
if (list != null) {
FeedAdapter adapter = new FeedAdapter(th...
setListAdapter(adapter);
}
}
}
private void showConfig() {
Intent intent = new Intent(getApplicationContext...
startActivity(intent);
}
}
~
-リスト5-21 DescActivity.java :
package com.beatcraft.rssreader;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.TextView;
public class DescActivity extends Activity implements Vi...
private static final String WEBVIEW_BEGIN =
"<html><head><meta http-equiv=\"Content-Type\" c...
private static final String WEBVIEW_LINK = "<p><a hr...
private static final String WEBVIEW_END = "</body></...
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.description);
Button button = (Button) findViewById(R.id.Back);
button.setOnClickListener(this);
Intent intent = getIntent();
if (intent != null) {
String tmp = "";
String desc = "";
TextView tv;
tv = (TextView) findViewById(R.id.FeedTitle);
tmp = intent.getStringExtra("FeedTitle");
tv.setText(tmp);
tv = (TextView) findViewById(R.id.ArticleTit...
tmp = intent.getStringExtra("ArticleTitle");
tv.setText(tmp);
tv = (TextView) findViewById(R.id.PubDate);
tmp = intent.getStringExtra("PubDate");
tv.setText(tmp);
WebView wv = (WebView) findViewById(R.id.Des...
desc = WEBVIEW_BEGIN;
tmp = intent.getStringExtra("Link");
desc += String.format(WEBVIEW_LINK, tmp, tmp);
tmp = intent.getStringExtra("Description");
desc += tmp + WEBVIEW_END;
wv.loadDataWithBaseURL("about:blank", desc, ...
}
}
@Override
public void onClick(View view) {
if (view.getId() == R.id.Back) {
finish();
}
}
}
~
-リスト5-22 ConfigActivity.java :
package com.beatcraft.rssreader;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager.LayoutParams;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
public class ConfigActivity extends Activity implements ...
public static final int REQUEST_RECOMMEND = 1234;
private static final int NUM_OF_GET_LIST[] = {1, 3, ...
private Spinner mNumOfGet;
private EditText mFeedURL[];
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setSoftInputMode(LayoutParams.S...
setContentView(R.layout.config);
RSSReaderApplication app = (RSSReaderApplication...
ArrayAdapter<CharSequence> adapter;
adapter = ArrayAdapter.createFromResource(this, ...
adapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_ite...
mNumOfGet = (Spinner) findViewById(R.id.NumOfGet);
mNumOfGet.setAdapter(adapter);
for (int i = 0; i < 3; ++i) {
if (NUM_OF_GET_LIST[i] == app.numberOfGet()) {
mNumOfGet.setSelection(i);
break;
}
}
mFeedURL = new EditText[RSSReaderApplication.NUM...
mFeedURL[0] = (EditText) findViewById(R.id.FeedU...
mFeedURL[1] = (EditText) findViewById(R.id.FeedU...
mFeedURL[2] = (EditText) findViewById(R.id.FeedU...
mFeedURL[3] = (EditText) findViewById(R.id.FeedU...
mFeedURL[4] = (EditText) findViewById(R.id.FeedU...
mFeedURL[5] = (EditText) findViewById(R.id.FeedU...
mFeedURL[6] = (EditText) findViewById(R.id.FeedU...
mFeedURL[7] = (EditText) findViewById(R.id.FeedU...
mFeedURL[8] = (EditText) findViewById(R.id.FeedU...
mFeedURL[9] = (EditText) findViewById(R.id.FeedU...
for (int i = 0; i < RSSReaderApplication.NUM_OF_...
mFeedURL[i].setText(app.feedURL(i));
}
Button button;
button = (Button) findViewById(R.id.Recommend);
button.setOnClickListener(this);
button = (Button) findViewById(R.id.Cancel);
button.setOnClickListener(this);
button = (Button) findViewById(R.id.Regist);
button.setOnClickListener(this);
}
@Override
public void onClick(View view) {
int id = view.getId();
switch (id) {
case R.id.Recommend:
showRecommend();
break;
case R.id.Cancel:
finish();
break;
case R.id.Regist:
regist();
break;
}
}
protected void onActivityResult(int reqCode, int res...
super.onActivityResult(reqCode, result, data);
if (result == RESULT_OK) {
if (reqCode == REQUEST_RECOMMEND) {
int count = 0;
count = data.getIntExtra("RecommendCount...
for (int i = 0; i < count; ++i) {
String key = "";
String url = "";
key = String.format("Recommend%02d",...
url = data.getStringExtra(key);
if (url.equals("") == false) {
for (int j = 0; j < RSSReaderApp...
String tmp = mFeedURL[j].get...
if (tmp.equals("") == true) {
mFeedURL[j].setText(url);
break;
}
}
}
}
}
}
}
private void showRecommend() {
Intent intent = new Intent(getApplicationContext...
startActivityForResult(intent, REQUEST_RECOMMEND);
}
private void regist() {
RSSReaderApplication app = (RSSReaderApplication...
app.setNumberOfGet(NUM_OF_GET_LIST[mNumOfGet.get...
app.clearFeedURL();
for (int i = 0, j = 0; i < RSSReaderApplication....
String url = mFeedURL[i].getText().toString(...
if (url.equals("") == false) {
app.setFeedURL(j++, url);
}
}
app.saveConfig();
finish();
}
}
~
-リスト5-23 RecommendActivity.java :
package com.beatcraft.rssreader;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.xmlpull.v1.XmlPullParser;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Xml;
import android.view.View;
import android.view.Window;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Spinner;
public class RecommendActivity extends Activity implemen...
private static final String GENRE[] = {"news", "musi...
private static final String POST_DOMAIN = "labs.beat...
private static final String POST_PATH = "/ja/android...
private static final String POST_USER = "beatandroid";
private static final String POST_PASS = "sample";
private static final int NUM_OF_RECOMMEND = 3;
private Spinner mGenre;
private CheckBox mFeedCheck[];
private String mRecommendTitle[];
private String mRecommendURL[];
private Button mAddFeed;
private int mStat = -1;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.recommend);
ArrayAdapter<CharSequence> adapter;
adapter = ArrayAdapter.createFromResource(this, ...
adapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_ite...
mGenre = (Spinner) findViewById(R.id.Genre);
mGenre.setAdapter(adapter);
Button button;
button = (Button) findViewById(R.id.Search);
button.setOnClickListener(this);
button = (Button) findViewById(R.id.Back);
button.setOnClickListener(this);
mAddFeed = (Button) findViewById(R.id.AddFeed);
mAddFeed.setOnClickListener(this);
mFeedCheck = new CheckBox[NUM_OF_RECOMMEND];
mFeedCheck[0] = (CheckBox) findViewById(R.id.Fee...
mFeedCheck[1] = (CheckBox) findViewById(R.id.Fee...
mFeedCheck[2] = (CheckBox) findViewById(R.id.Fee...
mRecommendTitle = new String[NUM_OF_RECOMMEND];
mRecommendURL = new String[NUM_OF_RECOMMEND];
}
@Override
public void onClick(View view) {
int id = view.getId();
switch (id) {
case R.id.Search:
HttpAccessTask task = new HttpAccessTask(thi...
task.execute(this);
break;
case R.id.Back:
finish();
break;
case R.id.AddFeed:
addFeed();
break;
}
}
@Override
public void backgroundProc() {
for (int i = 0; i < NUM_OF_RECOMMEND; ++i) {
mRecommendTitle[i] = "";
mRecommendURL[i] = "";
}
mStat = get(GENRE[mGenre.getSelectedItemPosition...
}
@Override
public void postProc() {
if (mStat == 0) {
for (int i = 0; i < NUM_OF_RECOMMEND; ++i) {
mFeedCheck[i].setText(mRecommendTitle[i]);
mFeedCheck[i].setVisibility(View.VISIBLE);
mFeedCheck[i].setChecked(false);
}
mAddFeed.setVisibility(View.VISIBLE);
}
else {
for (int i = 0; i < NUM_OF_RECOMMEND; ++i) {
mFeedCheck[i].setText("");
mFeedCheck[i].setVisibility(View.INVISIB...
mFeedCheck[i].setChecked(false);
}
mAddFeed.setVisibility(View.INVISIBLE);
}
}
private int get(String genre) {
String url = "http://" + POST_DOMAIN + POST_PATH;
DefaultHttpClient client = new DefaultHttpClient...
if (client != null) {
client.getParams().setParameter("http.socket...
HttpPost method = null;
try {
method = new HttpPost(url);
}
catch (Exception e) {
e.printStackTrace();
}
if (method == null) {
return -1;
}
HttpResponse response = null;
try {
List<NameValuePair> pair = new ArrayList...
pair.add(new BasicNameValuePair("genre",...
method.setEntity(new UrlEncodedFormEntit...
Credentials cred = new UsernamePasswordC...
client.getCredentialsProvider().setCrede...
response = client.execute(method);
int ret = response.getStatusLine().getSt...
if (ret == HttpStatus.SC_OK) {
InputStream is = response.getEntity(...
return parse(is);
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
client.getConnectionManager().shutdown();
}
}
return -1;
}
private int parse(InputStream is) {
int count = 0;
boolean inFeed = false;
XmlPullParser p = Xml.newPullParser();
try {
p.setInput(is, null);
int event = p.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
String elem = null;
String tmp = null;
switch (event) {
case XmlPullParser.START_TAG:
elem = p.getName();
if (elem.equals("feed") == true) {
if (inFeed == true) {
count++;
if (count >= NUM_OF_RECOMMEN...
return 0;
}
}
inFeed = true;
}
else if (elem.equals("title") == tru...
tmp = p.nextText();
if (tmp != null) {
mRecommendTitle[count] = tmp;
}
}
else if (elem.equals("url") == true) {
tmp = p.nextText();
if (tmp != null) {
mRecommendURL[count] = tmp;
}
}
break;
case XmlPullParser.END_TAG:
elem = p.getName();
if (elem.equals("feed") == true) {
count++;
if (count >= NUM_OF_RECOMMEND) {
return 0;
}
inFeed = false;
}
break;
}
event = p.next();
}
}
catch (Exception e) {
e.printStackTrace();
return -1;
}
return 0;
}
private void addFeed() {
int count = 0;
Intent result = new Intent();
for (int i = 0; i < NUM_OF_RECOMMEND; ++i) {
if (mFeedCheck[i].isChecked() == true) {
String key = "";
key = String.format("Recommend%02d", (co...
result.putExtra(key, mRecommendURL[i]);
count++;
}
}
result.putExtra("RecommendCount", count);
setResult(RESULT_OK, result);
finish();
}
}
~
-リスト5-24 FeedItem.java :
package com.beatcraft.rssreader;
public class FeedItem {
public static final int ITEMTYPE_FEEDCHANNEL = 0;
public static final int ITEMTYPE_FEEDITEM = 1;
private int mItemType;
private String mFeedTitle = "";
private String mArticleTitle = "";
private String mPubDate = "";
private String mDescription = "";
private String mLink = "";
public FeedItem(int itemType) {
mItemType = itemType;
}
public int itemType() {
return mItemType;
}
public String feedTitle() {
return mFeedTitle;
}
public void setFeedTitle(String title) {
mFeedTitle = title;
}
public String articleTitle() {
return mArticleTitle;
}
public void setArticleTitle(String title) {
mArticleTitle = title;
}
public String pubDate() {
return mPubDate;
}
public void setPubDate(String pubDate) {
mPubDate = pubDate;
}
public String description() {
return mDescription;
}
public void setDescription(String description) {
mDescription = description;
}
public String link() {
return mLink;
}
public void setLink(String link) {
mLink = link;
}
}
~
-リスト5-25 FeedList.java :
package com.beatcraft.rssreader;
import java.io.InputStream;
import java.util.ArrayList;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.xmlpull.v1.XmlPullParser;
import android.util.Xml;
public class FeedList {
private ArrayList<FeedItem> mList = null;
public FeedList() {
mList = new ArrayList<FeedItem>();
}
public ArrayList<FeedItem> getList() {
return mList;
}
public int count() {
if (mList != null) {
return mList.size();
}
return 0;
}
public int get(RSSReaderApplication app) {
int success = 0;
for (int i = 0; i < RSSReaderApplication.NUM_OF_...
String url = app.feedURL(i);
if (url.equals("") == true) {
continue;
}
DefaultHttpClient client = new DefaultHttpCl...
if (client != null) {
client.getParams().setParameter("http.so...
HttpGet method = null;
try {
method = new HttpGet(url);
}
catch (Exception e) {
e.printStackTrace();
}
if (method == null) {
continue;
}
HttpResponse response = null;
try {
response = client.execute(method);
int ret = response.getStatusLine().g...
if (ret == HttpStatus.SC_OK) {
InputStream is = response.getEnt...
if (parse(is, app.numberOfGet())...
success++;
}
is.close();
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
client.getConnectionManager().shutdo...
}
}
}
return success;
}
private int parse(InputStream is, int max) {
int count = 0;
boolean inChannel = false;
boolean inItem = false;
FeedItem item = null;
String feedTitle = "";
XmlPullParser p = Xml.newPullParser();
try {
p.setInput(is, null);
int event = p.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
String elem = null;
String tmp = null;
switch (event) {
case XmlPullParser.START_TAG:
elem = p.getName();
if (elem.equals("channel") == true) {
inChannel = true;
item = new FeedItem(FeedItem.ITE...
}
else if (elem.equals("item") == true...
if (inChannel == true) {
if (item != null) {
mList.add(item);
item = null;
count++;
}
inChannel = false;
}
inItem = true;
item = new FeedItem(FeedItem.ITE...
item.setFeedTitle(feedTitle);
}
else if (elem.equals("title") == tru...
tmp = p.nextText();
if ((tmp != null) && (item != nu...
if (inChannel == true) {
feedTitle = tmp;
item.setFeedTitle(tmp);
}
else if (inItem == true) {
item.setArticleTitle(tmp);
}
}
}
else if ((elem.equals("pubDate") == ...
|| (elem.equals("date") == t...
if (inItem == true) {
tmp = p.nextText();
if ((tmp != null) && (item !...
item.setPubDate(tmp);
}
}
}
else if (elem.equals("description") ...
if (inItem == true) {
tmp = p.nextText();
if ((tmp != null) && (item !...
item.setDescription(tmp);
}
}
}
else if (elem.equals("link") == true...
if (inItem == true) {
tmp = p.nextText();
if ((tmp != null) && (item !...
item.setLink(tmp);
}
}
}
break;
case XmlPullParser.END_TAG:
elem = p.getName();
if (elem.equals("channel") == true) {
if (inChannel == true) {
if (item != null) {
mList.add(item);
item = null;
count++;
}
inChannel = false;
}
}
else if (elem.equals("item") == true...
if (inItem == true) {
if (item != null) {
mList.add(item);
item = null;
count++;
max--;
if (max == 0) {
return count;
}
}
inItem = false;
}
}
}
event = p.next();
}
}
catch (Exception e) {
e.printStackTrace();
return 0;
}
return count;
}
}
~
-リスト5-26 FeedAdapter.java :
package com.beatcraft.rssreader;
import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class FeedAdapter extends ArrayAdapter<FeedItem> {
private LayoutInflater mInflate;
public FeedAdapter(Context context, List<FeedItem> o...
super(context, 0, obj);
mInflate = (LayoutInflater) context.getSystemSer...
}
@Override
public boolean isEnabled(int pos) {
FeedItem item = getItem(pos);
if (item.itemType() == FeedItem.ITEMTYPE_FEEDCHA...
return false;
}
return true;
}
public View getView(final int pos, View convView, Vi...
View view = convView;
FeedItem item = getItem(pos);
switch (item.itemType()) {
case FeedItem.ITEMTYPE_FEEDCHANNEL:
view = buildChannel(item);
break;
case FeedItem.ITEMTYPE_FEEDITEM:
view = buildItem(item);
break;
}
return view;
}
private View buildChannel(FeedItem item) {
View view = null;
view = mInflate.inflate(R.layout.item_channel, n...
TextView tv;
tv = (TextView) view.findViewById(R.id.FeedTitle);
tv.setText(item.feedTitle());
return view;
}
private View buildItem(FeedItem item) {
View view = null;
view = mInflate.inflate(R.layout.item_item, null);
TextView tv;
tv = (TextView) view.findViewById(R.id.ArticleTi...
tv.setText(item.articleTitle());
tv = (TextView) view.findViewById(R.id.PubDate);
tv.setText(item.pubDate());
return view;
}
}
~
-リスト5-27 ITaskEntity.java :
package com.beatcraft.rssreader;
public interface ITaskEntity {
void backgroundProc();
void postProc();
}
~
-リスト5-28 HttpAccessTask.java :
package com.beatcraft.rssreader;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
public class HttpAccessTask extends AsyncTask<ITaskEntit...
private Activity mActivity;
private ProgressDialog mDialog;
private ITaskEntity mITaskEntity;
public HttpAccessTask(Activity activity) {
mActivity = activity;
}
@Override
protected void onPreExecute() {
mDialog = new ProgressDialog(mActivity);
mDialog.setMessage(mActivity.getString(R.string....
mDialog.show();
}
@Override
protected Void doInBackground(ITaskEntity... params) {
mITaskEntity = params[0];
mITaskEntity.backgroundProc();
return null;
}
@Override
protected void onPostExecute(Void v) {
mITaskEntity.postProc();
mDialog.dismiss();
mDialog = null;
}
}
~
-リスト5-29 ListGenerateTask.java :
package com.beatcraft.rssreader;
import android.os.AsyncTask;
public class ListGenerateTask extends AsyncTask<ITaskEnt...
private ITaskEntity mITaskEntity;
@Override
protected Void doInBackground(ITaskEntity... params) {
mITaskEntity = params[0];
mITaskEntity.backgroundProc();
return null;
}
@Override
protected void onPostExecute(Void v) {
mITaskEntity.postProc();
}
}
~
-リスト5-30 FeedService.java :
package com.beatcraft.rssreader;
import java.util.ArrayList;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class FeedService extends Service implements Runn...
private static final String SERVICE_ACTION = "com.be...
private static final String BROADCAST_MSG = "com.bea...
private boolean mWorking = false;
private FeedList mListFG = null;
private FeedList mListBG = null;
@Override
public void onStart(Intent intent, int startID) {
super.onStart(intent, startID);
Thread thread = new Thread(this);
thread.run();
}
@Override
public IBinder onBind(Intent arg0) {
return mIFeedServiceBinder;
}
@Override
public void run() {
RSSReaderApplication app = (RSSReaderApplication...
mListBG = new FeedList();
if (mListBG.get(app) > 0) {
lock();
mListFG = mListBG;
unlock();
Intent bcast = new Intent(BROADCAST_MSG);
getBaseContext().sendBroadcast(bcast);
}
Intent ac = new Intent();
ac.setAction(SERVICE_ACTION);
PendingIntent pi = PendingIntent.getService(this...
AlarmManager am = (AlarmManager) getSystemServic...
long at = System.currentTimeMillis() + 60000;
am.set(AlarmManager.RTC, at, pi);
}
// service binder
private final IFeedService.Stub mIFeedServiceBinder ...
@Override
public void lockList() {
lock();
}
@Override
public void unlockList() {
unlock();
}
@Override
public int getFeedCount() throws RemoteException {
if (mListFG != null) {
return mListFG.count();
}
return 0;
}
@Override
public int getItemType(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.getLi...
return list.get(index).itemType();
}
return 0;
}
@Override
public String getFeedTitle(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.getLi...
return list.get(index).feedTitle();
}
return "";
}
@Override
public String getArticleTitle(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.getLi...
return list.get(index).articleTitle();
}
return "";
}
@Override
public String getPubDate(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.getLi...
return list.get(index).pubDate();
}
return "";
}
@Override
public String getDescription(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.getLi...
return list.get(index).description();
}
return "";
}
@Override
public String getLink(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.getLi...
return list.get(index).link();
}
return "";
}
};
private synchronized void lock() {
while (mWorking) {
try {
wait();
}
catch (Exception e) {
}
}
mWorking = true;
}
private synchronized void unlock() {
mWorking = false;
}
}
~
-リスト5-31 FeedReceiver.java :
package com.beatcraft.rssreader;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class FeedReceiver extends BroadcastReceiver {
IFeedReceiver mReceiver;
public FeedReceiver(IFeedReceiver receiver) {
mReceiver = receiver;
}
@Override
public void onReceive(Context context, Intent intent...
mReceiver.feedReceived();
}
}
~
-リスト5-32 IFeedReceiver.java :
package com.beatcraft.rssreader;
public interface IFeedReceiver {
void feedReceived();
}
~
-リスト5-33 IFeedService.aidl :
package com.beatcraft.rssreader;
interface IFeedService {
void lockList();
void unlockList();
int getFeedCount();
int getItemType(int index);
String getFeedTitle(int index);
String getArticleTitle(int index);
String getPubDate(int index);
String getDescription(int index);
String getLink(int index);
}
~
-リスト5-34 main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/...
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dip" >
<Button
android:id="@+id/Config"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:layout_weight="1"
android:text="@string/config" />
</LinearLayout>
<ListView
android:id="@+id/android:list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:fastScrollEnabled="true" >
</ListView>
</LinearLayout>
~
-リスト5-35 item_channel.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/...
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#cccccc"
android:orientation="vertical" >
<TextView
android:id="@+id/FeedTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="FeedTitle"
android:textColor="#000000"
android:textSize="16dip"
android:textStyle="bold" />
</LinearLayout>
~
-リスト5-36 item_item.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/...
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/ArticleTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="ArticleTitle" />
<TextView
android:id="@+id/PubDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_margin="5dip"
android:text="pubDate" />
</LinearLayout>
~
-リスト5-37 description.xml :
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/ap...
android:id="@+id/ScrollView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/Back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="@string/back" />
<TextView
android:id="@+id/FeedTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:text="FeedTitle"
android:textSize="16dip"
android:textStyle="bold" />
<TextView
android:id="@+id/ArticleTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:text="ArticleTitle" />
<TextView
android:id="@+id/PubDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="10dip"
android:text="pubDate" />
<android.webkit.WebView
android:id="@+id/Description"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_margin="5dip"
android:layout_weight="1" >
</android.webkit.WebView>
</LinearLayout>
</ScrollView>
~
-リスト5-38 config.xml :
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/ap...
android:id="@+id/ScrollView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dip" >
<TextView
android:id="@+id/LabelNumOfGet"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:text="@string/label_number_of_ge...
<Spinner
android:id="@+id/NumOfGet"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/Recommend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_weight="1"
android:text="@string/recommend" />
</LinearLayout>
<EditText
android:id="@+id/FeedURL01"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/FeedURL02"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<EditText
android:id="@+id/FeedURL03"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<EditText
android:id="@+id/FeedURL04"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<EditText
android:id="@+id/FeedURL05"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<EditText
android:id="@+id/FeedURL06"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<EditText
android:id="@+id/FeedURL07"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<EditText
android:id="@+id/FeedURL08"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<EditText
android:id="@+id/FeedURL09"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<EditText
android:id="@+id/FeedURL10"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<LinearLayout
android:id="@+id/linearLayout2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dip" >
<Button
android:id="@+id/Cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:layout_weight="1"
android:text="@string/cancel" />
<Button
android:id="@+id/Regist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:layout_weight="1"
android:text="@string/regist" />
</LinearLayout>
</LinearLayout>
</ScrollView>
~
-リスト5-39 recommend.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/...
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dip" >
<TextView
android:id="@+id/LabelGenre"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:text="@string/label_genre" />
<Spinner
android:id="@+id/Genre"
android:layout_width="120dip"
android:layout_height="wrap_content" />
<Button
android:id="@+id/Search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_weight="1"
android:text="@string/search" />
</LinearLayout>
<Button
android:id="@+id/Back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="@string/back" />
<CheckBox
android:id="@+id/Feed01"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="CheckBox"
android:visibility="invisible" />
<CheckBox
android:id="@+id/Feed02"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="CheckBox"
android:visibility="invisible" />
<CheckBox
android:id="@+id/Feed03"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="CheckBox"
android:visibility="invisible" />
<Button
android:id="@+id/AddFeed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="5dip"
android:text="@string/addfeed"
android:visibility="invisible" />
</LinearLayout>
~
-リスト5-40 AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/...
package="com.beatcraft.rssreader"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="7" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:name="com.beatcraft.rssreader.RSSReaderA...
<activity
android:label="@string/app_name"
android:name=".RSSReaderActivity" >
<intent-filter >
<action android:name="android.intent.act...
<category android:name="android.intent.c...
</intent-filter>
</activity>
<activity
android:label="@string/app_name"
android:name=".ConfigActivity" />
<activity
android:label="@string/app_name"
android:name=".DescActivity" />
<activity
android:label="@string/app_name"
android:name=".RecommendActivity" />
<service android:name=".FeedService" >
<intent-filter >
<action android:name="com.beatcraft.rssr...
</intent-filter>
</service>
</application>
<uses-permission android:name="android.permission.IN...
</uses-permission>
</manifest>
~
----
RIGHT:内藤
終了行:
[[Software/Android/アプリケーション開発テキスト]]
*Chapter 5 : サービスを利用したアプリケーションの作成 [#i...
この章ではサービスを利用して簡易RSSリーダーを拡張してい...
Chapter 4で作成した簡易RSSリーダーでは取得ボタンのタッ...
~
~
**5-1. サービスクラスの作成 [#a61c3b95]
まずはRSSReaderプロジェクトにバックグラウンドでRSSフィ...
android.app.ServiceをベースクラスとしたFeedServiceを生...
-リスト5-1 :
public class FeedService extends Service implements Runn...
private static final String SERVICE_ACTION = "com.b...
private static final String BROADCAST_MSG = "com.be...
private boolean mWorking = false;
private FeedList mListFG = null;
private FeedList mListBG = null;
~
定数SERVICE_ACTIONはこのサービスで取り扱うアクションを...
バックグラウンドでのフィード取得中に外部からリストを参...
続いてonStartメソッドを追加します(リスト5-2)。
-リスト5-2 :
@Override
public void onStart(Intent intent, int startID) {
super.onStart(intent, startID);
Thread thread = new Thread(this);
thread.run();
}
~
onStartはサービスが開始されると呼び出されるメソッドで、...
アクティビティなどのコンポーネントから直接サービスの機...
-リスト5-3 :
@Override
public IBinder onBind(Intent arg0) {
return mIFeedServiceBinder;
}
~
IBinder型のメンバ変数mIFeedServiceBinderを返すことで、...
前述の通り、このクラスにRunnableインターフェースを実装...
-リスト5-4 :
@Override
public void run() {
RSSReaderApplication app = (RSSReaderApplicati...
mListBG = new FeedList();
if (mListBG.get(app) > 0) {
lock();
mListFG = mListBG;
unlock();
Intent bcast = new Intent(BROADCAST_MSG);
getBaseContext().sendBroadcast(bcast);
}
Intent ac = new Intent(SERVICE_ACTION);
PendingIntent pi = PendingIntent.getService(th...
AlarmManager am = (AlarmManager) getSystemServ...
long at = System.currentTimeMillis() + 60000;
am.set(AlarmManager.RTC, at, pi);
}
~
runメソッドではまず、RSSReaderApplicationクラスのインス...
置き換えが終わったら定数BROADCAST_MSGをアクションに設定...
続いて定数SERVICE_ACTIONをアクションとして設定したイン...
ペンディングインテントの発行先としてこのサービスを指定...
これによりこのサービスが60秒毎に呼び出され、定期的なRSS...
サービスバインダーを追加します(リスト5-5)。IFeedServi...
-リスト5-5 :
// service binder
private final IFeedService.Stub mIFeedServiceBinder...
@Override
public void lockList() {
lock();
}
@Override
public void unlockList() {
unlock();
}
@Override
public int getFeedCount() throws RemoteExcepti...
if (mListFG != null) {
return mListFG.count();
}
return 0;
}
@Override
public int getItemType(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.g...
return list.get(index).itemType();
}
return 0;
}
@Override
public String getFeedTitle(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.g...
return list.get(index).feedTitle();
}
return "";
}
@Override
public String getArticleTitle(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.g...
return list.get(index).articleTitle();
}
return "";
}
@Override
public String getPubDate(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.g...
return list.get(index).pubDate();
}
return "";
}
@Override
public String getDescription(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.g...
return list.get(index).description();
}
return "";
}
@Override
public String getLink(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.g...
return list.get(index).link();
}
return "";
}
};
~
lockList/unlockListはRSSフィードリストを参照する際に排...
-リスト5-6 :
private synchronized void lock() {
while (mWorking) {
try {
wait();
}
catch (Exception e) {
}
}
mWorking = true;
}
private synchronized void unlock() {
mWorking = false;
}
~
最後に排他制御に使用するlock/unlockメソッドを追加します...
以上でサービスクラスの作成は完了です。引き続きAIDLファ...
Package ExplorerでRSSReaderのsrc/com.beatcraft.rssreade...
-リスト5-7 IFeedService.aidl :
package com.beatcraft.rssreader;
interface IFeedService {
void lockList();
void unlockList();
int getFeedCount();
int getItemType(int index);
String getFeedTitle(int index);
String getArticleTitle(int index);
String getPubDate(int index);
String getDescription(int index);
String getLink(int index);
}
~
作成されたIFeedService.aidlファイルを開き、リスト5-7の...
最後にRSSReaderのマニフェストファイル(AndroidManifest....
-リスト5-8 :
<service android:name=".FeedService" >
<intent-filter >
<action android:name="com.beatcraft.rssr...
</intent-filter>
</service>
~
インテントフィルタとして、サービスクラス内で定義した定...
~
~
**5-2. ブロードキャストレシーバの作成 [#d0e9ec46]
続いて、サービスが発行したブロードキャストを受信するブ...
android.content.BroadcastReceiverをベースクラスとしてFe...
-リスト5-9 FeedReceiver.java :
public class FeedReceiver extends BroadcastReceiver {
IFeedReceiver mReceiver;
public FeedReceiver(IFeedReceiver receiver) {
mReceiver = receiver;
}
@Override
public void onReceive(Context context, Intent inten...
mReceiver.feedReceived();
}
}
~
IFeedReceiverは受信したブロードキャストを実際に処理する...
続いてIFeedReceiverを作成するため、Package ExplorerでRS...
-リスト5-10 IFeedReceiver.java :
package com.beatcraft.rssreader;
public interface IFeedReceiver {
void feedReceived();
}
~
作成されたIFeedReceiver.javaを開き、feedReceivedメソッ...
以上でブロードキャストレシーバは完成です。
~
~
**5-3. サービスを利用する [#f59de66b]
サービスとブロードキャストレシーバが完成したので、ここ...
-リスト5-11 :
public class RSSReaderActivity extends ListActivity impl...
private static final String BROADCAST_MSG = "com.be...
private FeedList mList = null;
private IntentFilter mIFilter;
private IFeedService mIFeedServiceBind = null;
private ServiceConnection mServiceConnection = new ...
@Override
public void onServiceConnected(ComponentName n...
// インターフェースを取得
mIFeedServiceBind = IFeedService.Stub.asI...
}
@Override
public void onServiceDisconnected(ComponentNam...
//
}
};
~
IFeedReceiverのimplementsを追加し、ブロードキャスト受信...
引き続きITaskEntityがimplementsされていますが、これは従...
ボタンによるフィードの手動取得を廃止するため、onCreate...
-リスト5-12 :
button = (Button) findViewById(R.id.Get);
button.setOnClickListener(this);
~
-リスト5-13 :
case R.id.Get:
mList = null;
HttpAccessTask task = new HttpAccessTask(...
task.execute(this);
break;
~
続いてonCreateメソッドの最後に、ブロードキャストレシー...
-リスト5-14 :
FeedReceiver recv = new FeedReceiver(this);
mIFilter = new IntentFilter(BROADCAST_MSG);
registerReceiver(recv, mIFilter);
Intent intent = new Intent(getBaseContext(), Fee...
startService(intent);
bindService(intent, mServiceConnection, BIND_AUT...
~
先ほど実装したFeedReceiverを生成し、文字列定数BROADCAST...
FeedServiceを明示的に指定したインテントを生成し、startS...
インターフェースIFeedReceiver唯一のメソッドであるfeedRe...
-リスト5-15 :
@Override
public void feedReceived() {
ListGenerateTask task = new ListGenerateTask();
task.execute(this);
}
~
サービスがRSSフィードの取得を完了し、ブロードキャストを...
ListGenerateTaskは後ほど作成しますが、HttpAccessTask同...
修正後のbackgroundProcメソッドがリスト5-16になります。
-リスト5-16 :
@Override
public void backgroundProc() {
int count = 0;
mList = new FeedList();
if (mIFeedServiceBind != null) {
try {
mIFeedServiceBind.lockList();
count = mIFeedServiceBind.getFeedCoun...
FeedItem item;
for (int i = 0; i < count; ++i) {
int type = mIFeedServiceBind.get...
item = new FeedItem(type);
item.setFeedTitle(mIFeedServiceB...
item.setArticleTitle(mIFeedServi...
item.setPubDate(mIFeedServiceBin...
item.setDescription(mIFeedServic...
item.setLink(mIFeedServiceBind.g...
mList.getList().add(item);
}
mIFeedServiceBind.unlockList();
}
catch (RemoteException e) {
e.printStackTrace();
}
}
}
~
空のFeedListを生成したら、サービスバインダーのlockList...
ロックに成功したらフィードの数を取得し、フィード数分の...
-リスト5-17 :
@Override
public void postProc() {
if (mList.count() > 0) {
ArrayList<FeedItem> list = mList.getList();
if (list != null) {
FeedAdapter adapter = new FeedAdapte...
setListAdapter(adapter);
}
}
}
~
postProc(リスト5-17)ではバックグラウンドで生成したリ...
最後にListGenerateTaskを作成します。ベースクラスをAsync...
-リスト5-18 :
package com.beatcraft.rssreader;
import android.os.AsyncTask;
public class ListGenerateTask extends AsyncTask<ITaskEnt...
private ITaskEntity mITaskEntity;
@Override
protected Void doInBackground(ITaskEntity... params...
mITaskEntity = params[0];
mITaskEntity.backgroundProc();
return null;
}
@Override
protected void onPostExecute(Void v) {
mITaskEntity.postProc();
}
}
~
実際の処理はアクティビティに実装されたbackgroundProc/po...
以上で全ての実装は完了です。実行して動作を確認してみて...
~
~
**5-4. サービス版RSSReader全ソースコード/AIDLファイル/XML...
-リスト5-19 RSSReaderApplication.java :
package com.beatcraft.rssreader;
import android.app.Application;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
public class RSSReaderApplication extends Application {
private static final String CONF_NAME = "rssreader.c...
public static final int DEFAULT_NUM_OF_GET = 3;
public static final int NUM_OF_FEED = 10;
private int mNumOfGet = DEFAULT_NUM_OF_GET;
private String mFeedURL[];
@Override
public void onCreate() {
mFeedURL = new String[NUM_OF_FEED];
loadConfig();
}
public int numberOfGet() {
return mNumOfGet;
}
public void setNumberOfGet(int numOfGet) {
mNumOfGet = numOfGet;
}
public String feedURL(int index) {
if ((index < 0) || (10 <= index)) {
return null;
}
return mFeedURL[index];
}
public void setFeedURL(int index, String url) {
if ((index < 0) || (NUM_OF_FEED <= index)) {
return;
}
mFeedURL[index] = url;
}
public void clearFeedURL() {
for (int i = 0; i < NUM_OF_FEED; ++i) {
mFeedURL[i] = "";
}
}
public void loadConfig() {
SharedPreferences pref = getSharedPreferences(CO...
mNumOfGet = pref.getInt("NumOfGet", DEFAULT_NUM_...
for (int i = 0; i < NUM_OF_FEED; ++i) {
String key = String.format("FeedURL%02d", (i...
mFeedURL[i] = pref.getString(key, "");
}
}
public void saveConfig() {
SharedPreferences pref = getSharedPreferences(CO...
Editor pe = pref.edit();
pe.putInt("NumOfGet", mNumOfGet);
for (int i = 0; i < NUM_OF_FEED; ++i) {
String key = String.format("FeedURL%02d", (i...
pe.putString(key, mFeedURL[i]);
}
pe.commit();
}
}
~
-リスト5-20 RSSReaderActivity.java :
package com.beatcraft.rssreader;
import java.util.ArrayList;
import android.app.ListActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.Button;
public class RSSReaderActivity extends ListActivity impl...
private static final String BROADCAST_MSG = "com.bea...
private FeedList mList = null;
private IntentFilter mIFilter;
private IFeedService mIFeedServiceBind = null;
private ServiceConnection mServiceConnection = new S...
@Override
public void onServiceConnected(ComponentName nam...
// インターフェースを取得
mIFeedServiceBind = IFeedService.Stub.asInte...
}
@Override
public void onServiceDisconnected(ComponentName ...
//
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
Button button;
button = (Button) findViewById(R.id.Config);
button.setOnClickListener(this);
getListView().setOnItemClickListener(new Adapter...
@Override
public void onItemClick(AdapterView<?> paren...
FeedItem item = (FeedItem) getListView()...
Intent intent = new Intent(getApplicatio...
intent.putExtra("FeedTitle", item.feedTi...
intent.putExtra("ArticleTitle", item.art...
intent.putExtra("PubDate", item.pubDate(...
intent.putExtra("Description", item.desc...
intent.putExtra("Link", item.link());
startActivity(intent);
}
});
FeedReceiver recv = new FeedReceiver(this);
mIFilter = new IntentFilter(BROADCAST_MSG);
registerReceiver(recv, mIFilter);
Intent intent = new Intent(getBaseContext(), Fee...
startService(intent);
bindService(intent, mServiceConnection, BIND_AUT...
}
@Override
public void onClick(View view) {
int id = view.getId();
switch (id) {
case R.id.Config:
showConfig();
break;
}
}
@Override
public void feedReceived() {
ListGenerateTask task = new ListGenerateTask();
task.execute(this);
}
@Override
public void backgroundProc() {
int count = 0;
mList = new FeedList();
if (mIFeedServiceBind != null) {
try {
mIFeedServiceBind.lockList();
count = mIFeedServiceBind.getFeedCount();
FeedItem item;
for (int i = 0; i < count; ++i) {
int type = mIFeedServiceBind.getItem...
item = new FeedItem(type);
item.setFeedTitle(mIFeedServiceBind....
item.setArticleTitle(mIFeedServiceBi...
item.setPubDate(mIFeedServiceBind.ge...
item.setDescription(mIFeedServiceBin...
item.setLink(mIFeedServiceBind.getLi...
mList.getList().add(item);
}
mIFeedServiceBind.unlockList();
}
catch (RemoteException e) {
e.printStackTrace();
}
}
}
@Override
public void postProc() {
if (mList.count() > 0) {
ArrayList<FeedItem> list = mList.getList();
if (list != null) {
FeedAdapter adapter = new FeedAdapter(th...
setListAdapter(adapter);
}
}
}
private void showConfig() {
Intent intent = new Intent(getApplicationContext...
startActivity(intent);
}
}
~
-リスト5-21 DescActivity.java :
package com.beatcraft.rssreader;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.TextView;
public class DescActivity extends Activity implements Vi...
private static final String WEBVIEW_BEGIN =
"<html><head><meta http-equiv=\"Content-Type\" c...
private static final String WEBVIEW_LINK = "<p><a hr...
private static final String WEBVIEW_END = "</body></...
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.description);
Button button = (Button) findViewById(R.id.Back);
button.setOnClickListener(this);
Intent intent = getIntent();
if (intent != null) {
String tmp = "";
String desc = "";
TextView tv;
tv = (TextView) findViewById(R.id.FeedTitle);
tmp = intent.getStringExtra("FeedTitle");
tv.setText(tmp);
tv = (TextView) findViewById(R.id.ArticleTit...
tmp = intent.getStringExtra("ArticleTitle");
tv.setText(tmp);
tv = (TextView) findViewById(R.id.PubDate);
tmp = intent.getStringExtra("PubDate");
tv.setText(tmp);
WebView wv = (WebView) findViewById(R.id.Des...
desc = WEBVIEW_BEGIN;
tmp = intent.getStringExtra("Link");
desc += String.format(WEBVIEW_LINK, tmp, tmp);
tmp = intent.getStringExtra("Description");
desc += tmp + WEBVIEW_END;
wv.loadDataWithBaseURL("about:blank", desc, ...
}
}
@Override
public void onClick(View view) {
if (view.getId() == R.id.Back) {
finish();
}
}
}
~
-リスト5-22 ConfigActivity.java :
package com.beatcraft.rssreader;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager.LayoutParams;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
public class ConfigActivity extends Activity implements ...
public static final int REQUEST_RECOMMEND = 1234;
private static final int NUM_OF_GET_LIST[] = {1, 3, ...
private Spinner mNumOfGet;
private EditText mFeedURL[];
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setSoftInputMode(LayoutParams.S...
setContentView(R.layout.config);
RSSReaderApplication app = (RSSReaderApplication...
ArrayAdapter<CharSequence> adapter;
adapter = ArrayAdapter.createFromResource(this, ...
adapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_ite...
mNumOfGet = (Spinner) findViewById(R.id.NumOfGet);
mNumOfGet.setAdapter(adapter);
for (int i = 0; i < 3; ++i) {
if (NUM_OF_GET_LIST[i] == app.numberOfGet()) {
mNumOfGet.setSelection(i);
break;
}
}
mFeedURL = new EditText[RSSReaderApplication.NUM...
mFeedURL[0] = (EditText) findViewById(R.id.FeedU...
mFeedURL[1] = (EditText) findViewById(R.id.FeedU...
mFeedURL[2] = (EditText) findViewById(R.id.FeedU...
mFeedURL[3] = (EditText) findViewById(R.id.FeedU...
mFeedURL[4] = (EditText) findViewById(R.id.FeedU...
mFeedURL[5] = (EditText) findViewById(R.id.FeedU...
mFeedURL[6] = (EditText) findViewById(R.id.FeedU...
mFeedURL[7] = (EditText) findViewById(R.id.FeedU...
mFeedURL[8] = (EditText) findViewById(R.id.FeedU...
mFeedURL[9] = (EditText) findViewById(R.id.FeedU...
for (int i = 0; i < RSSReaderApplication.NUM_OF_...
mFeedURL[i].setText(app.feedURL(i));
}
Button button;
button = (Button) findViewById(R.id.Recommend);
button.setOnClickListener(this);
button = (Button) findViewById(R.id.Cancel);
button.setOnClickListener(this);
button = (Button) findViewById(R.id.Regist);
button.setOnClickListener(this);
}
@Override
public void onClick(View view) {
int id = view.getId();
switch (id) {
case R.id.Recommend:
showRecommend();
break;
case R.id.Cancel:
finish();
break;
case R.id.Regist:
regist();
break;
}
}
protected void onActivityResult(int reqCode, int res...
super.onActivityResult(reqCode, result, data);
if (result == RESULT_OK) {
if (reqCode == REQUEST_RECOMMEND) {
int count = 0;
count = data.getIntExtra("RecommendCount...
for (int i = 0; i < count; ++i) {
String key = "";
String url = "";
key = String.format("Recommend%02d",...
url = data.getStringExtra(key);
if (url.equals("") == false) {
for (int j = 0; j < RSSReaderApp...
String tmp = mFeedURL[j].get...
if (tmp.equals("") == true) {
mFeedURL[j].setText(url);
break;
}
}
}
}
}
}
}
private void showRecommend() {
Intent intent = new Intent(getApplicationContext...
startActivityForResult(intent, REQUEST_RECOMMEND);
}
private void regist() {
RSSReaderApplication app = (RSSReaderApplication...
app.setNumberOfGet(NUM_OF_GET_LIST[mNumOfGet.get...
app.clearFeedURL();
for (int i = 0, j = 0; i < RSSReaderApplication....
String url = mFeedURL[i].getText().toString(...
if (url.equals("") == false) {
app.setFeedURL(j++, url);
}
}
app.saveConfig();
finish();
}
}
~
-リスト5-23 RecommendActivity.java :
package com.beatcraft.rssreader;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.xmlpull.v1.XmlPullParser;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Xml;
import android.view.View;
import android.view.Window;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Spinner;
public class RecommendActivity extends Activity implemen...
private static final String GENRE[] = {"news", "musi...
private static final String POST_DOMAIN = "labs.beat...
private static final String POST_PATH = "/ja/android...
private static final String POST_USER = "beatandroid";
private static final String POST_PASS = "sample";
private static final int NUM_OF_RECOMMEND = 3;
private Spinner mGenre;
private CheckBox mFeedCheck[];
private String mRecommendTitle[];
private String mRecommendURL[];
private Button mAddFeed;
private int mStat = -1;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.recommend);
ArrayAdapter<CharSequence> adapter;
adapter = ArrayAdapter.createFromResource(this, ...
adapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_ite...
mGenre = (Spinner) findViewById(R.id.Genre);
mGenre.setAdapter(adapter);
Button button;
button = (Button) findViewById(R.id.Search);
button.setOnClickListener(this);
button = (Button) findViewById(R.id.Back);
button.setOnClickListener(this);
mAddFeed = (Button) findViewById(R.id.AddFeed);
mAddFeed.setOnClickListener(this);
mFeedCheck = new CheckBox[NUM_OF_RECOMMEND];
mFeedCheck[0] = (CheckBox) findViewById(R.id.Fee...
mFeedCheck[1] = (CheckBox) findViewById(R.id.Fee...
mFeedCheck[2] = (CheckBox) findViewById(R.id.Fee...
mRecommendTitle = new String[NUM_OF_RECOMMEND];
mRecommendURL = new String[NUM_OF_RECOMMEND];
}
@Override
public void onClick(View view) {
int id = view.getId();
switch (id) {
case R.id.Search:
HttpAccessTask task = new HttpAccessTask(thi...
task.execute(this);
break;
case R.id.Back:
finish();
break;
case R.id.AddFeed:
addFeed();
break;
}
}
@Override
public void backgroundProc() {
for (int i = 0; i < NUM_OF_RECOMMEND; ++i) {
mRecommendTitle[i] = "";
mRecommendURL[i] = "";
}
mStat = get(GENRE[mGenre.getSelectedItemPosition...
}
@Override
public void postProc() {
if (mStat == 0) {
for (int i = 0; i < NUM_OF_RECOMMEND; ++i) {
mFeedCheck[i].setText(mRecommendTitle[i]);
mFeedCheck[i].setVisibility(View.VISIBLE);
mFeedCheck[i].setChecked(false);
}
mAddFeed.setVisibility(View.VISIBLE);
}
else {
for (int i = 0; i < NUM_OF_RECOMMEND; ++i) {
mFeedCheck[i].setText("");
mFeedCheck[i].setVisibility(View.INVISIB...
mFeedCheck[i].setChecked(false);
}
mAddFeed.setVisibility(View.INVISIBLE);
}
}
private int get(String genre) {
String url = "http://" + POST_DOMAIN + POST_PATH;
DefaultHttpClient client = new DefaultHttpClient...
if (client != null) {
client.getParams().setParameter("http.socket...
HttpPost method = null;
try {
method = new HttpPost(url);
}
catch (Exception e) {
e.printStackTrace();
}
if (method == null) {
return -1;
}
HttpResponse response = null;
try {
List<NameValuePair> pair = new ArrayList...
pair.add(new BasicNameValuePair("genre",...
method.setEntity(new UrlEncodedFormEntit...
Credentials cred = new UsernamePasswordC...
client.getCredentialsProvider().setCrede...
response = client.execute(method);
int ret = response.getStatusLine().getSt...
if (ret == HttpStatus.SC_OK) {
InputStream is = response.getEntity(...
return parse(is);
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
client.getConnectionManager().shutdown();
}
}
return -1;
}
private int parse(InputStream is) {
int count = 0;
boolean inFeed = false;
XmlPullParser p = Xml.newPullParser();
try {
p.setInput(is, null);
int event = p.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
String elem = null;
String tmp = null;
switch (event) {
case XmlPullParser.START_TAG:
elem = p.getName();
if (elem.equals("feed") == true) {
if (inFeed == true) {
count++;
if (count >= NUM_OF_RECOMMEN...
return 0;
}
}
inFeed = true;
}
else if (elem.equals("title") == tru...
tmp = p.nextText();
if (tmp != null) {
mRecommendTitle[count] = tmp;
}
}
else if (elem.equals("url") == true) {
tmp = p.nextText();
if (tmp != null) {
mRecommendURL[count] = tmp;
}
}
break;
case XmlPullParser.END_TAG:
elem = p.getName();
if (elem.equals("feed") == true) {
count++;
if (count >= NUM_OF_RECOMMEND) {
return 0;
}
inFeed = false;
}
break;
}
event = p.next();
}
}
catch (Exception e) {
e.printStackTrace();
return -1;
}
return 0;
}
private void addFeed() {
int count = 0;
Intent result = new Intent();
for (int i = 0; i < NUM_OF_RECOMMEND; ++i) {
if (mFeedCheck[i].isChecked() == true) {
String key = "";
key = String.format("Recommend%02d", (co...
result.putExtra(key, mRecommendURL[i]);
count++;
}
}
result.putExtra("RecommendCount", count);
setResult(RESULT_OK, result);
finish();
}
}
~
-リスト5-24 FeedItem.java :
package com.beatcraft.rssreader;
public class FeedItem {
public static final int ITEMTYPE_FEEDCHANNEL = 0;
public static final int ITEMTYPE_FEEDITEM = 1;
private int mItemType;
private String mFeedTitle = "";
private String mArticleTitle = "";
private String mPubDate = "";
private String mDescription = "";
private String mLink = "";
public FeedItem(int itemType) {
mItemType = itemType;
}
public int itemType() {
return mItemType;
}
public String feedTitle() {
return mFeedTitle;
}
public void setFeedTitle(String title) {
mFeedTitle = title;
}
public String articleTitle() {
return mArticleTitle;
}
public void setArticleTitle(String title) {
mArticleTitle = title;
}
public String pubDate() {
return mPubDate;
}
public void setPubDate(String pubDate) {
mPubDate = pubDate;
}
public String description() {
return mDescription;
}
public void setDescription(String description) {
mDescription = description;
}
public String link() {
return mLink;
}
public void setLink(String link) {
mLink = link;
}
}
~
-リスト5-25 FeedList.java :
package com.beatcraft.rssreader;
import java.io.InputStream;
import java.util.ArrayList;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.xmlpull.v1.XmlPullParser;
import android.util.Xml;
public class FeedList {
private ArrayList<FeedItem> mList = null;
public FeedList() {
mList = new ArrayList<FeedItem>();
}
public ArrayList<FeedItem> getList() {
return mList;
}
public int count() {
if (mList != null) {
return mList.size();
}
return 0;
}
public int get(RSSReaderApplication app) {
int success = 0;
for (int i = 0; i < RSSReaderApplication.NUM_OF_...
String url = app.feedURL(i);
if (url.equals("") == true) {
continue;
}
DefaultHttpClient client = new DefaultHttpCl...
if (client != null) {
client.getParams().setParameter("http.so...
HttpGet method = null;
try {
method = new HttpGet(url);
}
catch (Exception e) {
e.printStackTrace();
}
if (method == null) {
continue;
}
HttpResponse response = null;
try {
response = client.execute(method);
int ret = response.getStatusLine().g...
if (ret == HttpStatus.SC_OK) {
InputStream is = response.getEnt...
if (parse(is, app.numberOfGet())...
success++;
}
is.close();
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
client.getConnectionManager().shutdo...
}
}
}
return success;
}
private int parse(InputStream is, int max) {
int count = 0;
boolean inChannel = false;
boolean inItem = false;
FeedItem item = null;
String feedTitle = "";
XmlPullParser p = Xml.newPullParser();
try {
p.setInput(is, null);
int event = p.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
String elem = null;
String tmp = null;
switch (event) {
case XmlPullParser.START_TAG:
elem = p.getName();
if (elem.equals("channel") == true) {
inChannel = true;
item = new FeedItem(FeedItem.ITE...
}
else if (elem.equals("item") == true...
if (inChannel == true) {
if (item != null) {
mList.add(item);
item = null;
count++;
}
inChannel = false;
}
inItem = true;
item = new FeedItem(FeedItem.ITE...
item.setFeedTitle(feedTitle);
}
else if (elem.equals("title") == tru...
tmp = p.nextText();
if ((tmp != null) && (item != nu...
if (inChannel == true) {
feedTitle = tmp;
item.setFeedTitle(tmp);
}
else if (inItem == true) {
item.setArticleTitle(tmp);
}
}
}
else if ((elem.equals("pubDate") == ...
|| (elem.equals("date") == t...
if (inItem == true) {
tmp = p.nextText();
if ((tmp != null) && (item !...
item.setPubDate(tmp);
}
}
}
else if (elem.equals("description") ...
if (inItem == true) {
tmp = p.nextText();
if ((tmp != null) && (item !...
item.setDescription(tmp);
}
}
}
else if (elem.equals("link") == true...
if (inItem == true) {
tmp = p.nextText();
if ((tmp != null) && (item !...
item.setLink(tmp);
}
}
}
break;
case XmlPullParser.END_TAG:
elem = p.getName();
if (elem.equals("channel") == true) {
if (inChannel == true) {
if (item != null) {
mList.add(item);
item = null;
count++;
}
inChannel = false;
}
}
else if (elem.equals("item") == true...
if (inItem == true) {
if (item != null) {
mList.add(item);
item = null;
count++;
max--;
if (max == 0) {
return count;
}
}
inItem = false;
}
}
}
event = p.next();
}
}
catch (Exception e) {
e.printStackTrace();
return 0;
}
return count;
}
}
~
-リスト5-26 FeedAdapter.java :
package com.beatcraft.rssreader;
import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class FeedAdapter extends ArrayAdapter<FeedItem> {
private LayoutInflater mInflate;
public FeedAdapter(Context context, List<FeedItem> o...
super(context, 0, obj);
mInflate = (LayoutInflater) context.getSystemSer...
}
@Override
public boolean isEnabled(int pos) {
FeedItem item = getItem(pos);
if (item.itemType() == FeedItem.ITEMTYPE_FEEDCHA...
return false;
}
return true;
}
public View getView(final int pos, View convView, Vi...
View view = convView;
FeedItem item = getItem(pos);
switch (item.itemType()) {
case FeedItem.ITEMTYPE_FEEDCHANNEL:
view = buildChannel(item);
break;
case FeedItem.ITEMTYPE_FEEDITEM:
view = buildItem(item);
break;
}
return view;
}
private View buildChannel(FeedItem item) {
View view = null;
view = mInflate.inflate(R.layout.item_channel, n...
TextView tv;
tv = (TextView) view.findViewById(R.id.FeedTitle);
tv.setText(item.feedTitle());
return view;
}
private View buildItem(FeedItem item) {
View view = null;
view = mInflate.inflate(R.layout.item_item, null);
TextView tv;
tv = (TextView) view.findViewById(R.id.ArticleTi...
tv.setText(item.articleTitle());
tv = (TextView) view.findViewById(R.id.PubDate);
tv.setText(item.pubDate());
return view;
}
}
~
-リスト5-27 ITaskEntity.java :
package com.beatcraft.rssreader;
public interface ITaskEntity {
void backgroundProc();
void postProc();
}
~
-リスト5-28 HttpAccessTask.java :
package com.beatcraft.rssreader;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
public class HttpAccessTask extends AsyncTask<ITaskEntit...
private Activity mActivity;
private ProgressDialog mDialog;
private ITaskEntity mITaskEntity;
public HttpAccessTask(Activity activity) {
mActivity = activity;
}
@Override
protected void onPreExecute() {
mDialog = new ProgressDialog(mActivity);
mDialog.setMessage(mActivity.getString(R.string....
mDialog.show();
}
@Override
protected Void doInBackground(ITaskEntity... params) {
mITaskEntity = params[0];
mITaskEntity.backgroundProc();
return null;
}
@Override
protected void onPostExecute(Void v) {
mITaskEntity.postProc();
mDialog.dismiss();
mDialog = null;
}
}
~
-リスト5-29 ListGenerateTask.java :
package com.beatcraft.rssreader;
import android.os.AsyncTask;
public class ListGenerateTask extends AsyncTask<ITaskEnt...
private ITaskEntity mITaskEntity;
@Override
protected Void doInBackground(ITaskEntity... params) {
mITaskEntity = params[0];
mITaskEntity.backgroundProc();
return null;
}
@Override
protected void onPostExecute(Void v) {
mITaskEntity.postProc();
}
}
~
-リスト5-30 FeedService.java :
package com.beatcraft.rssreader;
import java.util.ArrayList;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class FeedService extends Service implements Runn...
private static final String SERVICE_ACTION = "com.be...
private static final String BROADCAST_MSG = "com.bea...
private boolean mWorking = false;
private FeedList mListFG = null;
private FeedList mListBG = null;
@Override
public void onStart(Intent intent, int startID) {
super.onStart(intent, startID);
Thread thread = new Thread(this);
thread.run();
}
@Override
public IBinder onBind(Intent arg0) {
return mIFeedServiceBinder;
}
@Override
public void run() {
RSSReaderApplication app = (RSSReaderApplication...
mListBG = new FeedList();
if (mListBG.get(app) > 0) {
lock();
mListFG = mListBG;
unlock();
Intent bcast = new Intent(BROADCAST_MSG);
getBaseContext().sendBroadcast(bcast);
}
Intent ac = new Intent();
ac.setAction(SERVICE_ACTION);
PendingIntent pi = PendingIntent.getService(this...
AlarmManager am = (AlarmManager) getSystemServic...
long at = System.currentTimeMillis() + 60000;
am.set(AlarmManager.RTC, at, pi);
}
// service binder
private final IFeedService.Stub mIFeedServiceBinder ...
@Override
public void lockList() {
lock();
}
@Override
public void unlockList() {
unlock();
}
@Override
public int getFeedCount() throws RemoteException {
if (mListFG != null) {
return mListFG.count();
}
return 0;
}
@Override
public int getItemType(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.getLi...
return list.get(index).itemType();
}
return 0;
}
@Override
public String getFeedTitle(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.getLi...
return list.get(index).feedTitle();
}
return "";
}
@Override
public String getArticleTitle(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.getLi...
return list.get(index).articleTitle();
}
return "";
}
@Override
public String getPubDate(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.getLi...
return list.get(index).pubDate();
}
return "";
}
@Override
public String getDescription(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.getLi...
return list.get(index).description();
}
return "";
}
@Override
public String getLink(int index) {
if (mListFG != null) {
ArrayList<FeedItem> list = mListFG.getLi...
return list.get(index).link();
}
return "";
}
};
private synchronized void lock() {
while (mWorking) {
try {
wait();
}
catch (Exception e) {
}
}
mWorking = true;
}
private synchronized void unlock() {
mWorking = false;
}
}
~
-リスト5-31 FeedReceiver.java :
package com.beatcraft.rssreader;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class FeedReceiver extends BroadcastReceiver {
IFeedReceiver mReceiver;
public FeedReceiver(IFeedReceiver receiver) {
mReceiver = receiver;
}
@Override
public void onReceive(Context context, Intent intent...
mReceiver.feedReceived();
}
}
~
-リスト5-32 IFeedReceiver.java :
package com.beatcraft.rssreader;
public interface IFeedReceiver {
void feedReceived();
}
~
-リスト5-33 IFeedService.aidl :
package com.beatcraft.rssreader;
interface IFeedService {
void lockList();
void unlockList();
int getFeedCount();
int getItemType(int index);
String getFeedTitle(int index);
String getArticleTitle(int index);
String getPubDate(int index);
String getDescription(int index);
String getLink(int index);
}
~
-リスト5-34 main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/...
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dip" >
<Button
android:id="@+id/Config"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:layout_weight="1"
android:text="@string/config" />
</LinearLayout>
<ListView
android:id="@+id/android:list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:fastScrollEnabled="true" >
</ListView>
</LinearLayout>
~
-リスト5-35 item_channel.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/...
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#cccccc"
android:orientation="vertical" >
<TextView
android:id="@+id/FeedTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="FeedTitle"
android:textColor="#000000"
android:textSize="16dip"
android:textStyle="bold" />
</LinearLayout>
~
-リスト5-36 item_item.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/...
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/ArticleTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="ArticleTitle" />
<TextView
android:id="@+id/PubDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_margin="5dip"
android:text="pubDate" />
</LinearLayout>
~
-リスト5-37 description.xml :
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/ap...
android:id="@+id/ScrollView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/Back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="@string/back" />
<TextView
android:id="@+id/FeedTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:text="FeedTitle"
android:textSize="16dip"
android:textStyle="bold" />
<TextView
android:id="@+id/ArticleTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:text="ArticleTitle" />
<TextView
android:id="@+id/PubDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="10dip"
android:text="pubDate" />
<android.webkit.WebView
android:id="@+id/Description"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_margin="5dip"
android:layout_weight="1" >
</android.webkit.WebView>
</LinearLayout>
</ScrollView>
~
-リスト5-38 config.xml :
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/ap...
android:id="@+id/ScrollView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dip" >
<TextView
android:id="@+id/LabelNumOfGet"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:text="@string/label_number_of_ge...
<Spinner
android:id="@+id/NumOfGet"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/Recommend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_weight="1"
android:text="@string/recommend" />
</LinearLayout>
<EditText
android:id="@+id/FeedURL01"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/FeedURL02"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<EditText
android:id="@+id/FeedURL03"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<EditText
android:id="@+id/FeedURL04"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<EditText
android:id="@+id/FeedURL05"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<EditText
android:id="@+id/FeedURL06"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<EditText
android:id="@+id/FeedURL07"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<EditText
android:id="@+id/FeedURL08"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<EditText
android:id="@+id/FeedURL09"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<EditText
android:id="@+id/FeedURL10"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:inputType="textUri" />
<LinearLayout
android:id="@+id/linearLayout2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dip" >
<Button
android:id="@+id/Cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:layout_weight="1"
android:text="@string/cancel" />
<Button
android:id="@+id/Regist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:layout_weight="1"
android:text="@string/regist" />
</LinearLayout>
</LinearLayout>
</ScrollView>
~
-リスト5-39 recommend.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/...
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dip" >
<TextView
android:id="@+id/LabelGenre"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:text="@string/label_genre" />
<Spinner
android:id="@+id/Genre"
android:layout_width="120dip"
android:layout_height="wrap_content" />
<Button
android:id="@+id/Search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_weight="1"
android:text="@string/search" />
</LinearLayout>
<Button
android:id="@+id/Back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="@string/back" />
<CheckBox
android:id="@+id/Feed01"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="CheckBox"
android:visibility="invisible" />
<CheckBox
android:id="@+id/Feed02"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="CheckBox"
android:visibility="invisible" />
<CheckBox
android:id="@+id/Feed03"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="CheckBox"
android:visibility="invisible" />
<Button
android:id="@+id/AddFeed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="5dip"
android:text="@string/addfeed"
android:visibility="invisible" />
</LinearLayout>
~
-リスト5-40 AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/...
package="com.beatcraft.rssreader"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="7" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:name="com.beatcraft.rssreader.RSSReaderA...
<activity
android:label="@string/app_name"
android:name=".RSSReaderActivity" >
<intent-filter >
<action android:name="android.intent.act...
<category android:name="android.intent.c...
</intent-filter>
</activity>
<activity
android:label="@string/app_name"
android:name=".ConfigActivity" />
<activity
android:label="@string/app_name"
android:name=".DescActivity" />
<activity
android:label="@string/app_name"
android:name=".RecommendActivity" />
<service android:name=".FeedService" >
<intent-filter >
<action android:name="com.beatcraft.rssr...
</intent-filter>
</service>
</application>
<uses-permission android:name="android.permission.IN...
</uses-permission>
</manifest>
~
----
RIGHT:内藤
ページ名:
BC::labsへの質問は、bc9-dev @ googlegroups.com までお願い致します。