android:configChanges="touchscreen|keyboard"
android:theme="@android:style/Theme.Black"
android:launchMode="standard"
- android:noHistory="true"
android:description="@string/app_description">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
+
+ <activity
+ android:label="@string/app_name"
+ android:name=".list.MobiAdsNewAdsActivity"
+ android:theme="@android:style/Theme.Black"
+ android:screenOrientation="portrait"
+ android:configChanges="touchscreen|keyboard" >
+ <intent-filter>
+ <action android:name="android.intent.action.MOBIADSNEWADS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
<service
- android:name=".MobiAdsService"
- android:process=":mobiadsservice" >
+ android:name=".MobiAdsService" >
</service>
<provider
android:permission="android.permission.MOBIADS"
android:readPermission="android.permission.READ_MOBIADS"
android:syncable="false"
- android:writePermission="android.permission.WRITE_MOBIADS"
- android:process=":mobiadsservice" >
+ android:writePermission="android.permission.WRITE_MOBIADS">
<grant-uri-permission android:pathPattern=".*" />
</provider>
public static final int wheelnotification=0x7f020002;
}
public static final class id {
- public static final int ads_entry_icon=0x7f05000f;
- public static final int ads_entry_text=0x7f050011;
- public static final int ads_entry_title=0x7f050010;
+ public static final int ads_entry_icon=0x7f05000e;
+ public static final int ads_entry_text=0x7f050010;
+ public static final int ads_entry_title=0x7f05000f;
public static final int button_bind=0x7f050007;
- public static final int button_lislocalads=0x7f05000e;
- public static final int button_startservice=0x7f05000c;
- public static final int button_stopservice=0x7f05000a;
+ public static final int button_lislocalads=0x7f05000d;
+ public static final int button_startservice=0x7f05000b;
+ public static final int button_stopservice=0x7f050009;
public static final int button_unbind=0x7f050008;
- public static final int cancel_button=0x7f050005;
public static final int frameLayout1=0x7f050000;
public static final int frameLayout2=0x7f050003;
- public static final int frameLayout3=0x7f050009;
- public static final int frameLayout4=0x7f05000b;
- public static final int frameLayout5=0x7f05000d;
+ public static final int frameLayout3=0x7f050005;
+ public static final int frameLayout4=0x7f05000a;
+ public static final int frameLayout5=0x7f05000c;
public static final int list=0x7f050006;
public static final int login_button=0x7f050004;
public static final int password=0x7f050002;
public static final int main=0x7f030000;
public static final int mobiadslist=0x7f030001;
public static final int mobiadsmain=0x7f030002;
- public static final int news_entry_list_item=0x7f030003;
+ public static final int mobiadsnewadslist=0x7f030003;
+ public static final int news_entry_list_item=0x7f030004;
}
public static final class string {
- public static final int alert_dialog_cancel=0x7f040003;
- public static final int app_description=0x7f040002;
- public static final int app_name=0x7f040001;
- public static final int button_cancel=0x7f04000f;
- public static final int button_login=0x7f040008;
- public static final int button_messagebind=0x7f040009;
- public static final int button_messagelistlocalads=0x7f04000d;
- public static final int button_messagestartservice=0x7f04000c;
- public static final int button_messagestopservice=0x7f04000b;
- public static final int button_messageunbind=0x7f04000a;
- public static final int button_ok=0x7f04000e;
- public static final int desc=0x7f040017;
- public static final int encoded_web_service=0x7f040016;
- public static final int error_dialog_connection_error=0x7f040004;
- public static final int error_dialog_userpwd_error=0x7f040005;
+ public static final int alert_dialog_cancel=0x7f040004;
+ public static final int app_description=0x7f040003;
+ public static final int app_name=0x7f040002;
+ public static final int button_cancel=0x7f040010;
+ public static final int button_localads=0x7f040011;
+ public static final int button_login=0x7f040009;
+ public static final int button_messagebind=0x7f04000a;
+ public static final int button_messagelistlocalads=0x7f04000e;
+ public static final int button_messagestartservice=0x7f04000d;
+ public static final int button_messagestopservice=0x7f04000c;
+ public static final int button_messageunbind=0x7f04000b;
+ public static final int button_ok=0x7f04000f;
+ public static final int desc=0x7f04001d;
+ public static final int encoded_web_service=0x7f04001c;
+ public static final int error_dialog_connection_error=0x7f040005;
+ public static final int error_dialog_userpwd_error=0x7f040006;
public static final int hello=0x7f040000;
- public static final int password=0x7f040007;
- public static final int remote_service_label=0x7f040012;
- public static final int remote_service_started=0x7f040010;
- public static final int remote_service_stopped=0x7f040011;
- public static final int url_login_web_service=0x7f040013;
- public static final int url_web=0x7f040014;
- public static final int user_agent_web_service=0x7f040015;
- public static final int username=0x7f040006;
+ public static final int new_ads=0x7f040001;
+ public static final int password=0x7f040008;
+ public static final int remote_service_content_empty_notification=0x7f040015;
+ public static final int remote_service_content_notification=0x7f040014;
+ public static final int remote_service_new_ads=0x7f040012;
+ public static final int remote_service_received_ad_notification=0x7f040013;
+ public static final int remote_service_started_notification=0x7f040016;
+ public static final int remote_service_stopped_notification=0x7f040017;
+ public static final int remote_service_title_notification=0x7f040018;
+ public static final int url_login_web_service=0x7f040019;
+ public static final int url_web=0x7f04001a;
+ public static final int user_agent_web_service=0x7f04001b;
+ public static final int username=0x7f040007;
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:gravity="right"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:weightSum="1">
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:weightSum="1" >
<FrameLayout
android:id="@+id/frameLayout1"
<EditText
android:id="@+id/password"
- android:password="true"
+ android:inputType="textPassword"
android:singleLine="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
<Button
android:id="@+id/login_button"
android:onClick="onClickLogin"
- android:layout_height="wrap_content"
+ android:layout_height="70dp"
android:text="@string/button_login"
android:layout_width="match_parent"
android:layout_gravity="center"/>
- <Button
- android:id="@+id/cancel_button"
- android:onClick="onClickCancel"
- android:gravity="right"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_gravity="right"
- android:text="@string/button_cancel"/>
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:id="@+id/frameLayout3"
+ android:layout_height="30dp">
+ </FrameLayout>
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <Button android:layout_weight="1"
+ android:layout_height="wrap_content"
+ android:layout_width="0dip"
+ android:onClick="onClickLocalAds"
+ android:text="@string/button_localads" />
+ <Button android:layout_weight="1"
+ android:layout_height="wrap_content"
+ android:layout_width="0dip"
+ android:onClick="onClickCancel"
+ android:text="@string/button_cancel" />
+ </LinearLayout>
+
</LinearLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/new_ads" />
+
+ <ListView android:id="@+id/list"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" />
+
+</LinearLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item android:id="@+id/menuads"
+ android:title="string"
+ android:titleCondensed="string"
+ android:icon="@[package:]drawable/drawable_resource_name"
+ android:onClick="method name"
+ android:showAsAction=["ifRoom" | "never" | "withText" | "always" | "collapseActionView"]
+ android:actionLayout="@[package:]layout/layout_resource_name"
+ android:actionViewClass="class name"
+ android:actionProviderClass="class name"
+ android:alphabeticShortcut="string"
+ android:numericShortcut="string"
+ android:checkable=["true" | "false"]
+ android:visible=["true" | "false"]
+ android:enabled=["true" | "false"]
+ android:menuCategory=["container" | "system" | "secondary" | "alternative"]
+ android:orderInCategory="integer" />
+ <group android:id="@[+][package:]id/resource name"
+ android:checkableBehavior=["none" | "all" | "single"]
+ android:visible=["true" | "false"]
+ android:enabled=["true" | "false"]
+ android:menuCategory=["container" | "system" | "secondary" | "alternative"]
+ android:orderInCategory="integer" >
+ <item />
+ </group>
+ <item >
+ <menu>
+ <item />
+ </menu>
+ </item>
+
+
+</menu>
\ No newline at end of file
<resources>
<string name="hello">Android MobiAds!</string>
+ <string name="new_ads">Latest received Ads</string>
<string name="app_name">MobiAds</string>
<string name="app_description">Receive notifications about offers and discounts.</string>
<string name="alert_dialog_cancel">Do you really want to close the application?</string>
<string name="button_messagelistlocalads">List Your Ads</string>
<string name="button_ok">OK</string>
<string name="button_cancel">Cancel</string>
- <string name="remote_service_started">MobiAds Service Started</string>
- <string name="remote_service_stopped">MobiAds Service Stopped</string>
- <string name="remote_service_label">MobiAds Service</string>
+ <string name="button_localads">Local Ads</string>
+ <string name="remote_service_new_ads"> new Ads downloaded for you.</string>
+ <string name="remote_service_received_ad_notification">Received Ad</string>
+ <string name="remote_service_content_notification">New Ads waiting for you</string>
+ <string name="remote_service_content_empty_notification">No new Ads waiting for you</string>
+ <string name="remote_service_started_notification">MobiAds Service Started</string>
+ <string name="remote_service_stopped_notification">MobiAds Service Stopped</string>
+ <string name="remote_service_title_notification">MobiAds Service</string>
<string name="url_login_web_service">http://users.mobiads.gumartinm.name/userfront.php/api/login/auth.json</string>
<string name="url_web">users.mobiads.gumartinm.name</string>
<string name="user_agent_web_service">MobieAds/1.0</string>
HttpEntity httpEntity = null;
HttpResponse httpResponse = null;
final List<NameValuePair> formParams = new ArrayList<NameValuePair>(2);
-
+
httpClient.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, getResources().getString(R.string.encoded_web_service));
httpClient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, getResources().getString(R.string.user_agent_web_service));
httpClient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
setComponent(new ComponentName("de.android.mobiads", "de.android.mobiads.MobiAdsMainActivity"));
intent.putExtra("cookie", cookie);
this.startActivity(intent);
+ this.finish();
} else {
Log.e(TAG, "There must be a weird issue with the server because... There is not cookie!!!!");
createErrorDialog(R.string.error_dialog_connection_error);
}
}
+ public void onClickLocalAds(View v) {
+ Intent intent = new Intent("android.intent.action.MOBIADSLIST").
+ setComponent(new ComponentName("de.android.mobiads", "de.android.mobiads.list.MobiAdsListActivity"));
+ this.startActivity(intent);
+ }
+
public void onClickCancel(View v) {
createAlertDialog(R.string.alert_dialog_cancel);
}
package de.android.mobiads;
import android.app.Activity;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
-import android.os.Handler;
import android.os.IBinder;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
import android.view.View;
public class MobiAdsMainActivity extends Activity {
- /** For showing and hiding our notification. */
- private NotificationManager notificationManager;
- /** Messenger for communicating with service. */
- Messenger mService = null;
+ /** Communicating with local service. */
+ MobiAdsService mBoundService = null;
/** Flag indicating whether we have called bind on the service. */
boolean mIsBound;
/**
* Target we publish for clients to send messages to IncomingHandler.
*/
- final Messenger mMessenger = new Messenger(new IncomingHandler());
- /**TODO: I should send a message to the service to find out if the service is running instead of this boolean field.*/
- private boolean isEnabledService;
private static String cookie;
@Override
public void onResume() {
- if (this.isEnabledService) {
- this.showNotification(0);
- }
super.onResume();
}
/**
- * Handler of incoming messages from service.
- */
- class IncomingHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MobiAdsService.MSG_SET_VALUE:
- break;
- default:
- super.handleMessage(msg);
- }
- }
- }
-
-
-
- /**
* Class for interacting with the main interface of the service.
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
- // This is called when the connection with the service has been
+ // This is called when the connection with the service has been
// established, giving us the service object we can use to
- // interact with the service. We are communicating with our
- // service through an IDL interface, so get a client-side
- // representation of that from the raw service object.
- mService = new Messenger(service);
-
- // We want to monitor the service for as long as we are
- // connected to it.
- try {
- Message msg = Message.obtain(null,
- MobiAdsService.MSG_REGISTER_CLIENT);
- msg.replyTo = mMessenger;
- mService.send(msg);
-
- // Give it some value as an example.
- msg = Message.obtain(null,
- MobiAdsService.MSG_SET_VALUE, this.hashCode(), 0);
- mService.send(msg);
- } catch (RemoteException e) {
- // In this case the service has crashed before we could even
- // do anything with it; we can count on soon being
- // disconnected (and then reconnected if it can be restarted)
- // so there is no need to do anything here.
- }
+ // interact with the service. Because we have bound to a explicit
+ // service that we know is running in our own process, we can
+ // cast its IBinder to a concrete class and directly access it.
+ mBoundService = ((MobiAdsService.LocalBinder)service).getService();
}
public void onServiceDisconnected(ComponentName className) {
- // This is called when the connection with the service has been
+ // This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
- mService = null;
+ // Because it is running in our same process, we should never
+ // see this happen.
+ mBoundService = null;
+
}
};
// Establish a connection with the service. We use an explicit
// class name because there is no reason to be able to let other
// applications replace our component.
- boolean prueba = bindService(new Intent(MobiAdsMainActivity.this,
+ mIsBound = bindService(new Intent(MobiAdsMainActivity.this,
MobiAdsService.class), mConnection, Context.BIND_AUTO_CREATE);
- mIsBound = true;
}
public void onClickStopService(View v) {
this.stopService(new Intent(MobiAdsMainActivity.this, MobiAdsService.class));
- this.isEnabledService = false;
}
public void onClickStartService(View v) {
Intent intent = new Intent(MobiAdsMainActivity.this, MobiAdsService.class);
intent.putExtra("cookie", MobiAdsMainActivity.cookie);
- this.notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
- this.isEnabledService = true;
this.startService(intent);
}
setComponent(new ComponentName("de.android.mobiads", "de.android.mobiads.list.MobiAdsListActivity"));
this.startActivity(intent);
}
-
- /**
- * Show a notification while this service is running.
- */
- public void showNotification(int level) {
-
- Intent intent = new Intent(this, MobiAdsMainActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
- // The PendingIntent to launch our activity if the user selects this notification
- PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
-
-
- // Set the icon, scrolling text and timestamp
- Notification.Builder notificationBuilder = new Notification.Builder(getApplicationContext()).
- setSmallIcon(R.drawable.wheelnotification, level).
- setTicker(getText(R.string.remote_service_started)).
- setWhen(System.currentTimeMillis()).
- setContentText(getText(R.string.remote_service_started)).
- setContentTitle(getText(R.string.remote_service_label)).
- setContentIntent(contentIntent);
- Notification notification = notificationBuilder.getNotification();
- notification.flags |= Notification.FLAG_NO_CLEAR;
-
- // Send the notification.
- // We use a string id because it is a unique number. We use it later to cancel.
- notificationManager.notify(R.string.remote_service_started, notification);
- }
}
package de.android.mobiads;
import de.android.mobiads.batch.MobiAdsBatch;
+import de.android.mobiads.list.MobiAdsNewAdsActivity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
+import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
private LocationManager locationManager;
private LocationListener locationListener;
+
+ /**
+ * Class for clients to access. Because we know this service always
+ * runs in the same process as its clients, we don't need to deal with
+ * IPC.
+ */
+ public class LocalBinder extends Binder {
+ MobiAdsService getService() {
+ return MobiAdsService.this;
+ }
+ }
+
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
// Display a notification about us starting.
- showNotification(0);
-
+ int noReadCount = 0;
+ CharSequence contentText;
+ if ((noReadCount = this.mobiAdsBatch.noReadAdsCount()) == 0) {
+ contentText = getText(R.string.remote_service_content_empty_notification);
+ }
+ else {
+ contentText = getText(R.string.remote_service_content_notification);
+ }
+ showNotification(0, noReadCount, contentText);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
// Cancel the persistent notification.
- notificationManager.cancel(R.string.remote_service_started);
+ notificationManager.cancel(R.string.remote_service_title_notification);
if (this.locationListener != null) {
this.locationManager.removeUpdates(this.locationListener);
/**
* Show a notification while this service is running.
*/
- public void showNotification(int level) {
+ public void showNotification(final int level, final int noReadAds, CharSequence contentText) {
- Intent intent = new Intent(this, MobiAdsMainActivity.class);
+ Intent intent = new Intent(this, MobiAdsNewAdsActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
-
-
+
// Set the icon, scrolling text and timestamp
Notification.Builder notificationBuilder = new Notification.Builder(getApplicationContext()).
setSmallIcon(R.drawable.wheelnotification, level).
- setTicker(getText(R.string.remote_service_started)).
+ setTicker(getText(R.string.remote_service_started_notification)).
setWhen(System.currentTimeMillis()).
- setContentText(getText(R.string.remote_service_started)).
- setContentTitle(getText(R.string.remote_service_label)).
- setContentIntent(contentIntent);
+ setContentText(contentText).
+ setContentTitle(getText(R.string.remote_service_title_notification)).
+ setNumber(noReadAds).
+ setContentIntent(contentIntent);
Notification notification = notificationBuilder.getNotification();
notification.flags |= Notification.FLAG_NO_CLEAR;
// Send the notification.
// We use a string id because it is a unique number. We use it later to cancel.
- notificationManager.notify(R.string.remote_service_started, notification);
+ notificationManager.notify(R.string.remote_service_title_notification, notification);
}
}
import android.net.http.AndroidHttpClient;
import android.util.Log;
import de.android.mobiads.MobiAdsService;
+import de.android.mobiads.R;
import de.android.mobiads.provider.Indexer;
public class MobiAdsBatch {
if ((uriInsert = updatedIndexer(objects)) != null) {
try {
downloadAds((String)objects.get("image"), (String) objects.get("id"));
- ((MobiAdsService)MobiAdsBatch.this.context).showNotification(1);
+ int noReadCount = 0;
+ CharSequence contentText;
+ if ((noReadCount = MobiAdsBatch.this.noReadAdsCount()) == 0) {
+ contentText = ((MobiAdsService)MobiAdsBatch.this.context).
+ getText(R.string.remote_service_content_empty_notification);
+ }
+ else {
+ contentText = ((MobiAdsService)MobiAdsBatch.this.context).
+ getText(R.string.remote_service_content_notification);
+ }
+ ((MobiAdsService)MobiAdsBatch.this.context).
+ showNotification(0, noReadCount, contentText);
+
} catch (Throwable e1) {
//In case of any error, remove the index database and the file
//or chunk successfully stored before the error.
//getContentResolver().query method never returns Cursor with null value.
//TODO: review my code in order to find more cases like this. :(
//Be aware with the RunTimeExceptions. Apparently Java needs try/catch blocks in everywhere...
+ //TODO this method outside updatedIndexer. It is all about semantic and good design. No time sorry...
+ //Open an issue about improving my code some day...
Cursor cursor = MobiAdsBatch.this.context.getContentResolver().query(uri, null, null, null, null);
try {
if (!cursor.moveToFirst()) {
values.put(Indexer.Index.COLUMN_NAME_PATH, (String) objects.get("id"));
values.put(Indexer.Index.COLUMN_NAME_TEXT, (String) objects.get("text"));
values.put(Indexer.Index.COLUMN_NAME_URL, (String) objects.get("link"));
+ values.put(Indexer.Index.COLUMN_NAME_IS_READ, new Integer(0));
//This method may throw SQLiteException (as a RunTimeException). So, without a try/catch block
//there could be a leaked cursor...
//TODO: review code looking for more cases like this one...
return updated;
}
}
+
+
+ public int noReadAdsCount() {
+ Uri uri = Uri.parse("content://" + "de.android.mobiads.provider" + "/" + "indexer" + "/isRead/");
+
+ Cursor cursor = MobiAdsBatch.this.context.getContentResolver().query(uri, null, null, null, null);
+ int count = 0;
+
+ try {
+ count = cursor.getCount();
+ } finally {
+ cursor.close();
+ }
+
+ return count;
+ }
}
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-
-import de.android.mobiads.MobiAdsMainActivity;
-import de.android.mobiads.R;
-import de.android.mobiads.provider.Indexer;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
-import android.os.Bundle;
import android.util.Log;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.MenuInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
+import de.android.mobiads.R;
+import de.android.mobiads.provider.Indexer;
public class MobiAdsListActivity extends Activity {
private static final String TAG = "MobiAdsListActivity";
@Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ public void onResume() {
+ super.onResume();
setContentView(R.layout.mobiadslist);
// Setup the list view
final AdsEntryAdapter newsEntryAdapter = new AdsEntryAdapter(this, R.layout.news_entry_list_item);
newsEntryListView.setAdapter(newsEntryAdapter);
+ this.registerForContextMenu(newsEntryListView);
// Populate the list, through the adapter. Should I populate the whole list right now? I do not think so...
// Find out a way to populate this list just when it is required... :/
for(final AdsEntry entry : getAdsEntries()) {
private List<AdsEntry> getAdsEntries() {
final List<AdsEntry> entries = new ArrayList<AdsEntry>();
final Uri uri = Uri.parse("content://" + "de.android.mobiads.provider" + "/" + "indexer");
+ final ContentValues values = new ContentValues();
Cursor cursor = this.getContentResolver().query(uri, null, null, null, null);
try {
if (cursor.moveToFirst()) {
do {
+ values.clear();
Bitmap bitMap = null;
FileInputStream file = null;
try {
file = this.openFileInput(cursor.getString(cursor.getColumnIndexOrThrow(Indexer.Index.COLUMN_NAME_PATH)));
bitMap = BitmapFactory.decodeStream(file);
} catch (FileNotFoundException e) {
+ //Giving more chances to other ads
continue;
} catch (IllegalArgumentException e) {
+ //Giving more chances to other ads
continue;
}
finally {
}
}
entries.add(new AdsEntry(cursor.getString(cursor.getColumnIndexOrThrow(Indexer.Index.COLUMN_NAME_URL)),
- cursor.getString(cursor.getColumnIndexOrThrow(Indexer.Index.COLUMN_NAME_TEXT)), bitMap));
+ cursor.getString(cursor.getColumnIndexOrThrow(Indexer.Index.COLUMN_NAME_TEXT)), bitMap));
+ if (cursor.getInt(cursor.getColumnIndexOrThrow(Indexer.Index.COLUMN_NAME_IS_READ)) == 0)
+ {
+ values.put(Indexer.Index.COLUMN_NAME_IS_READ, new Integer(1));
+ Uri uriUpdate = Uri.parse("content://" + "de.android.mobiads.provider" + "/" + "indexer/" +
+ cursor.getString(cursor.getColumnIndexOrThrow(Indexer.Index._ID)));
+ getContentResolver().update(uriUpdate, values, null, null);
+ }
}while (cursor.moveToNext());
}
}finally {
cursor.close();
}
+ showNotification(0, 0, getText(R.string.remote_service_content_empty_notification));
+
return entries;
}
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, v, menuInfo);
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.menuads, menu);
+ }
+
+
+ public void showNotification(final int level, final int noReadAds, CharSequence contentText) {
+ NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
+ Intent intent = new Intent(this, MobiAdsNewAdsActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
+ // The PendingIntent to launch our activity if the user selects this notification
+ PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+ // Set the icon, scrolling text and timestamp
+ Notification.Builder notificationBuilder = new Notification.Builder(getApplicationContext()).
+ setSmallIcon(R.drawable.wheelnotification, level).
+ setTicker(getText(R.string.remote_service_started_notification)).
+ setWhen(System.currentTimeMillis()).
+ setContentText(contentText).
+ setContentTitle(getText(R.string.remote_service_title_notification)).
+ setNumber(noReadAds).
+ setContentIntent(contentIntent);
+ Notification notification = notificationBuilder.getNotification();
+ notification.flags |= Notification.FLAG_NO_CLEAR;
+
+ // Send the notification.
+ // We use a string id because it is a unique number. We use it later to cancel.
+ notificationManager.notify(R.string.remote_service_title_notification, notification);
+ }
}
\ No newline at end of file
--- /dev/null
+package de.android.mobiads.list;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import de.android.mobiads.R;
+import de.android.mobiads.provider.Indexer;
+import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+import android.widget.AdapterView.OnItemClickListener;
+
+public class MobiAdsNewAdsActivity extends Activity {
+ private static final String TAG = "MobiAdsNewAdsActivity";
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ setContentView(R.layout.mobiadsnewadslist);
+
+ // Setup the list view
+ final ListView newsEntryListView = (ListView) findViewById(R.id.list);
+ final AdsEntryAdapter newsEntryAdapter = new AdsEntryAdapter(this, R.layout.news_entry_list_item);
+ newsEntryListView.setAdapter(newsEntryAdapter);
+
+ // Populate the list, through the adapter. Should I populate the whole list right now? I do not think so...
+ // Find out a way to populate this list just when it is required... :/
+ for(final AdsEntry entry : getAdsEntries()) {
+ newsEntryAdapter.add(entry);
+ }
+
+ newsEntryListView.setOnItemClickListener(new OnItemClickListener() {
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ Uri uri = Uri.parse(newsEntryAdapter.getItem(position).getTitle());
+ startActivity(new Intent(Intent.ACTION_VIEW, uri));
+ }
+ });
+
+ }
+
+ private List<AdsEntry> getAdsEntries() {
+ final List<AdsEntry> entries = new ArrayList<AdsEntry>();
+ final Uri uri = Uri.parse("content://" + "de.android.mobiads.provider" + "/" + "indexer" + "/isRead/");
+ final ContentValues values = new ContentValues();
+
+ Cursor cursor = this.getContentResolver().query(uri, null, null, null, null);
+ try {
+ if (cursor.moveToFirst()) {
+ do {
+ values.clear();
+ Bitmap bitMap = null;
+ FileInputStream file = null;
+
+ try {
+ file = this.openFileInput(cursor.getString(cursor.getColumnIndexOrThrow(Indexer.Index.COLUMN_NAME_PATH)));
+ bitMap = BitmapFactory.decodeStream(file);
+ } catch (FileNotFoundException e) {
+ //Giving more chances to other ads
+ continue;
+ } catch (IllegalArgumentException e) {
+ //Giving more chances to other ads
+ continue;
+ }
+ finally {
+ if (file != null) {
+ try {
+ file.close();
+ } catch (IOException e) {
+ Log.w(TAG, "Error while closing image file.");
+ }
+ }
+ }
+ entries.add(new AdsEntry(cursor.getString(cursor.getColumnIndexOrThrow(Indexer.Index.COLUMN_NAME_URL)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Indexer.Index.COLUMN_NAME_TEXT)), bitMap));
+
+
+ cursor.getString(cursor.getColumnIndexOrThrow(Indexer.Index.COLUMN_NAME_PATH));
+ values.put(Indexer.Index.COLUMN_NAME_IS_READ, new Integer(1));
+ Uri uriUpdate = Uri.parse("content://" + "de.android.mobiads.provider" + "/" + "indexer/" +
+ cursor.getString(cursor.getColumnIndexOrThrow(Indexer.Index._ID)));
+ getContentResolver().update(uriUpdate, values, null, null);
+ }while (cursor.moveToNext());
+ }
+ }finally {
+ cursor.close();
+ }
+
+
+ showNotification(0, 0, getText(R.string.remote_service_content_empty_notification));
+
+ return entries;
+ }
+
+ public void showNotification(final int level, final int noReadAds, CharSequence contentText) {
+ NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
+ Intent intent = new Intent(this, MobiAdsNewAdsActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
+ // The PendingIntent to launch our activity if the user selects this notification
+ PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+ // Set the icon, scrolling text and timestamp
+ Notification.Builder notificationBuilder = new Notification.Builder(getApplicationContext()).
+ setSmallIcon(R.drawable.wheelnotification, level).
+ setTicker(getText(R.string.remote_service_started_notification)).
+ setWhen(System.currentTimeMillis()).
+ setContentText(contentText).
+ setContentTitle(getText(R.string.remote_service_title_notification)).
+ setNumber(noReadAds).
+ setContentIntent(contentIntent);
+ Notification notification = notificationBuilder.getNotification();
+ notification.flags |= Notification.FLAG_NO_CLEAR;
+
+ // Send the notification.
+ // We use a string id because it is a unique number. We use it later to cancel.
+ notificationManager.notify(R.string.remote_service_title_notification, notification);
+ }
+}
public static final String COLUMN_NAME_URL = "url";
/**
+ * Column name for the Sqlite3 integer as boolean field. <br>
+ * It let us know if the ad was already read by the user or not.
+ * <P>Type: TEXT</P>
+ */
+ public static final String COLUMN_NAME_IS_READ = "isRead";
+
+ /**
* The default sort order for this table
*/
public static final String DEFAULT_SORT_ORDER = Index._ID;
+ Indexer.Index.COLUMN_NAME_ID_AD + " INTEGER" + " UNIQUE" + " NOT NULL, "
+ Indexer.Index.COLUMN_NAME_PATH + " TEXT(15)" + " UNIQUE" + " NOT NULL, "
+ Indexer.Index.COLUMN_NAME_URL + " TEXT(2000)" + " NOT NULL, "
- + Indexer.Index.COLUMN_NAME_TEXT + " TEXT(255)" + " NOT NULL"
+ + Indexer.Index.COLUMN_NAME_TEXT + " TEXT(255)" + " NOT NULL, "
+ + Indexer.Index.COLUMN_NAME_IS_READ + " INTEGER" + " NOT NULL "
+ ");");
}
private static final int INDEXER_IDAD = 3;
+ private static final int NOREAD = 4;
+
static {
/*
sUriMatcher.addURI("de.android.mobiads.provider", Indexer.Index.TABLE_NAME + "/" + Indexer.Index.COLUMN_NAME_ID_AD + "/#", INDEXER_IDAD);
+ sUriMatcher.addURI("de.android.mobiads.provider", Indexer.Index.TABLE_NAME + "/" + Indexer.Index.COLUMN_NAME_IS_READ, NOREAD);
/*
* Creates and initializes a projection map that returns all columns
sIndexerProjectionMap.put(Indexer.Index.COLUMN_NAME_TEXT, Indexer.Index.COLUMN_NAME_TEXT);
sIndexerProjectionMap.put(Indexer.Index.COLUMN_NAME_URL, Indexer.Index.COLUMN_NAME_URL);
+
+ sIndexerProjectionMap.put(Indexer.Index.COLUMN_NAME_IS_READ, Indexer.Index.COLUMN_NAME_IS_READ);
}
if ((values.containsKey(Indexer.Index.COLUMN_NAME_PATH) == false) ||
(values.containsKey(Indexer.Index.COLUMN_NAME_ID_AD) == false) ||
(values.containsKey(Indexer.Index.COLUMN_NAME_TEXT) == false) ||
- (values.containsKey(Indexer.Index.COLUMN_NAME_URL) == false)){
+ (values.containsKey(Indexer.Index.COLUMN_NAME_URL) == false) ||
+ (values.containsKey(Indexer.Index.COLUMN_NAME_IS_READ) == false)){
throw new SQLException("Missed parameter. Failed to insert row into " + uri);
}
// the position of the Advertisement ID itself in the incoming URI
uri.getPathSegments().get(2));
break;
+ case NOREAD:
+ qb.setProjectionMap(sIndexerProjectionMap);
+ qb.appendWhere(Indexer.Index.COLUMN_NAME_IS_READ + " = " + "0");
+ break;
default:
// If the URI doesn't match any of the known patterns, throw an exception.
throw new IllegalArgumentException("Unknown URI " + uri);
// null if the values are in the where argument.
);
break;
-
+
+ case NOREAD:
+ finalWhere = Indexer.Index.COLUMN_NAME_IS_READ + " = " + "0";
+ if (where !=null) {
+ finalWhere = finalWhere + " AND " + where;
+ }
+ // Does the update and returns the number of rows updated.
+ count = db.update(
+ Indexer.Index.TABLE_NAME, // The database table name.
+ values, // A map of column names and new values to use.
+ finalWhere, // The final WHERE clause to use
+ // placeholders for whereArgs
+ whereArgs // The where clause column values to select on, or
+ // null if the values are in the where argument.
+ );
+ break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}