i am using dependency service to use Android MediaPlayer, however once i return the value from media player to shared project the value mediaplayer is null. I have seen and tried https://github.com/xamarin/xamarin-forms-samples/blob/master/UserInterface/MediaElementDemos/MediaElementDemos.Android/VideoPicker.cs
My interface
public interface IDictionaryPlayer
{
MediaPlayer SetGong(int timeoutBetweenWords);
}
Droid
public MediaPlayer SetGong(int timeout)
{
MediaPlayer pausesPlayer = MediaPlayer.Create(Android.App.Application.Context, Resource.Raw.gong);
return pausesPlayer;
}
Shared project
public static MediaPlayer GongPlayer;
public static void SetPauseOrGongBetweenWords(int timeoutBetweenWords)
{
GongPlayer = DependencyService.Get<IDictionaryPlayer>().SetGong(timeoutBetweenWords); // HERE ITS NULL
initialize = true;
GongPlayer.Start();
}
public static void TryPausePlayer()
{
lock (playerLock)
{
if (GongPlayer != null && GongPlayer.IsPlaying)
{
gongNeedsResume = true;
GongPlayer?.Pause();
}
}
}
public static void TryResumePlayer()
{
if (gongNeedsResume)
{
gongNeedsResume = false;
GongPlayer?.Start();
}
}
internal static void Clean()
{
disposeActive = true;
if (GongPlayer != null)
{
GongPlayer.Dispose();
GongPlayer = null;
}
}
Related
I have implemented WebViewRenderer it works well on Android but it doesn't work on iOS. It displays the value, but then user clicks next button and the value doesn't update. I have tried the the example on ms website, but that displayed no text, I don't have the values from URL. I have also tried several post here.
[assembly: ExportRenderer(typeof(ExtendedWebView), typeof(ExtendedWebViewRenderer))]
namespace MyApp.iOS.Renderers
{
public class ExtendedWebViewRenderer : ViewRenderer<ExtendedWebView, WKWebView>
{
WKWebView _wkWebView;
static ExtendedWebView _xwebView = null;
protected override void OnElementChanged(ElementChangedEventArgs<ExtendedWebView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
WKWebViewConfiguration config = new WKWebViewConfiguration();
_wkWebView = new WKWebView(Frame, config);
_wkWebView.NavigationDelegate = new CustomWKNavigationDelegate(this);
SetNativeControl(_wkWebView);
}
if (e.NewElement != null)
{
HtmlWebViewSource source = (Xamarin.Forms.HtmlWebViewSource)Element.Source;
string html = source.Html;
_wkWebView.LoadHtmlString(html, baseUrl: null);
_wkWebView.ScrollView.ScrollEnabled = false;
_wkWebView.SizeToFit();
}
}
}
public class CustomWKNavigationDelegate : WKNavigationDelegate
{
ExtendedWebViewRenderer _webViewRenderer;
public CustomWKNavigationDelegate(ExtendedWebViewRenderer webViewRenderer)
{
_webViewRenderer = webViewRenderer;
}
public override async void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
{
var wv = _webViewRenderer.Element as ExtendedWebView;
if (wv != null)
{
await System.Threading.Tasks.Task.Delay(100); // wait here till content is rendered
wv.HeightRequest = (double)webView.ScrollView.ContentSize.Height;
}
}
}
}
[assembly: ExportRenderer(typeof(ExtendedWebView), typeof(ExtendedWebViewRenderer))]
namespace MyApp.Droid.Renderers
{
public class ExtendedWebViewRenderer : WebViewRenderer
{
public static int _webViewHeight;
static ExtendedWebView _xwebView = null;
public WebView _webView;
bool isScroll;
[Obsolete]
public ExtendedWebViewRenderer(Context context) : base(context)
{
}
class ExtendedWebViewClient : WebViewClient
{
WebView _webView;
public async override void OnPageFinished(WebView view, string url)
{
try
{
_webView = view;
if (_xwebView != null)
{
view.Settings.JavaScriptEnabled = true;
await Task.Delay(100);
string result = await _xwebView.EvaluateJavaScriptAsync("(function(){return document.body.scrollHeight;})()");
_xwebView.HeightRequest = Convert.ToDouble(result);
}
base.OnPageFinished(view, url);
}
catch (Exception ex)
{
Console.WriteLine($"{ex.Message}");
}
}
public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, IWebResourceRequest request)
{
return true;
}
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
_xwebView = e.NewElement as ExtendedWebView;
_webView = Control;
if (e.OldElement == null)
{
_webView.SetWebViewClient(new ExtendedWebViewClient());
}
}
}
}
public class ExtendedWebView : WebView
{
public ExtendedWebView()
{
}
}
XAML
<controls:ExtendedWebView
VerticalOptions="FillAndExpand" Grid.RowSpan="2"
x:Name="enView"
Opacity="1"
Source="{Binding CZ, Mode=TwoWay}"/>
private static HtmlWebViewSource htmlSourceExplanation = new HtmlWebViewSource();
public HtmlWebViewSource Cz
{
get { return _cz; }
set
{
_cz = value;
NotifyPropertyChanged(nameof(Cz));
}
}
private void SetExplanationDetail(string text, string text2)
{
htmlSourceExplanation.Html = _style + "<div class=\"text\"><div>" + text + "</div><div>" + text2 + "</div></div>";
_cz = htmlSourceExplanation;
NotifyPropertyChanged("Cz");
}
I expect the value to change once to user cliks the button. `
Below are shown my classes of sysOperation framework, my problem is when i open the dialog and i press OK , nothing happens, what's wrong with this code?
My service class:
class ProdutionFLowsService extends SysOperationServiceBase
{
ProductionFlowId idOfCopy;
int copyToDo;
ProdTable prodTable;
public void process(ProdutionFLowsContract _contract)
{
this.getPromptParameters(_contract);
select firstonly ProdId
from prodTable
order by ProdId
where prodTable.ProductionFlowId == this.idOfCopy;
this.insertInProdTable();
}
public void insertInProdTable()
{
ProdTable _prodTable;
while(copyToDo > 0)
{
buf2Buf(prodTable,_prodTable);
_prodTable.RecId = 0;
_prodTable.ProdId = _prodTable.Type().initProdId(true);
_prodTable.GAP035ProductionFlowId = _prodTable.ProductionFlowId;
_prodTable.insert();
copyToDo--;
}
}
public void getPromptParameters(ProdutionFLowsContract _contract)
{
copyToDo = _contract.parmCopyToDo();
idOfCopy = _contract.parmidOfCopy();
}
}
My controller class:
class ProdutionFLowsController extends SysOperationServiceController
{
public void new()
{
super();
super(classStr(ProdutionFLowsService), methodStr(ProdutionFLowsService, process), SysOperationExecutionMode::Synchronous);
this.parmDialogCaption("TODO");
}
public static void main(Args _args)
{
ProdutionFLowsController controller = new ProdutionFLowsController();
controller.parmArgs(_args);
controller.startOperation();
}
}
My Contract Class:
[DataContractAttribute]
class ProdutionFLowsContract implements SysOperationInitializable,SysOperationValidatable
{
ProductionFlowId idOfCopy;
int copyToDo;
public void initialize()
{
idOfCopy = "";
copyToDo = 0;
}
[DataMemberAttribute("idOfCopy"),SysOperationLabelAttribute(literalStr("TODO(Id)")),SysOperationDisplayOrderAttribute("1")]
public ProductionFlowId parmidOfCopy(ProductionFlowId _idOfCopy = idOfCopy)
{
idOfCopy = _idOfCopy;
return idOfCopy;
}
[DataMemberAttribute("copyToDo"),SysOperationLabelAttribute(literalStr("copyToDo(Copy)")),SysOperationDisplayOrderAttribute("2")]
public int parmCopyToDo(int _copyToDo = copyToDo)
{
copyToDo = _copyToDo;
return copyToDo;
}
public boolean validate()
{
return false;
}
}
Your contract validation always fails because it always returns false and doesn't show any error in the infolog:
public boolean validate()
{
return false;
}
Try to replace return false with return true or to remove SysOperationValidatable and validate method altogether.
I get "unfortunately app has stopped" error after phone restart. My Phone is Oreo 8 but another phone with Nougat 7.1.1 also having the same error after phone restart. I use James Montemagnos' MyStepCounter bound services codes from GitHub with some changes in VS 2017 (Xamarin Cross-Platform App). The app is working fine if once started after phone restart with this error, else it is not counting steps and not working on the background. If I check the app in Phone Settings-General-Battery-Power saving exclusions then it works with no problems after phone restart and it is counting steps on the background without starting the app on Oreo phone. But there are no settings for battery power saving exclusions on the other phone
BootReceiver.cs
[BroadcastReceiver(Enabled = true, Exported = true, DirectBootAware = true)]
[IntentFilter(new string[] { Intent.ActionBootCompleted, Intent.ActionLockedBootCompleted, "android.intent.action.QUICKBOOT_POWERON", "com.htc.intent.action.QUICKBOOT_POWERON" })]
public class BootReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
var stepServiceIntent = new Intent(context, typeof(StepService));
context.StartService(stepServiceIntent);
}
}
StepServiceBinder.cs
public class StepServiceBinder : Binder
{
StepService stepService;
public StepServiceBinder(StepService service)
{
this.stepService = service;
}
public StepService StepService
{
get { return stepService; }
}
}
StepServiceConnection.cs
public class StepServiceConnection : Java.Lang.Object, IServiceConnection
{
MainActivity activity;
public StepServiceConnection(MainActivity activity)
{
this.activity = activity;
}
public void OnServiceConnected(ComponentName name, IBinder service)
{
var serviceBinder = service as StepServiceBinder;
if (serviceBinder != null)
{
activity.Binder = serviceBinder;
activity.IsBound = true;
}
}
public void OnServiceDisconnected(ComponentName name)
{
activity.IsBound = false;
}
}
StepService.cs
public class StepServiceConnection : Java.Lang.Object, IServiceConnection
{
MainActivity activity;
public StepServiceConnection(MainActivity activity)
{
this.activity = activity;
}
public void OnServiceConnected(ComponentName name, IBinder service)
{
var serviceBinder = service as StepServiceBinder;
if (serviceBinder != null)
{
activity.Binder = serviceBinder;
activity.IsBound = true;
}
}
public void OnServiceDisconnected(ComponentName name)
{
activity.IsBound = false;
}
}
StepService.cs
[Service(Enabled = true)]
[IntentFilter(new String[] { "com.PedometerApp.StepService" })]
public class StepService : Service, ISensorEventListener, INotifyPropertyChanged
{
private SensorManager sManager;
private bool isRunning;
private long stepsToday = 0;
public bool WarningState
{
get;
set;
}
public long StepsToday
{
get { return stepsToday; }
set
{
if (stepsToday == value)
return;
stepsToday = value;
OnPropertyChanged("StepsToday");
Settings.CurrentDaySteps = value;
MessagingCenter.Send<object, long>(this, "Steps", Settings.CurrentDaySteps);
}
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
var alarmManager = ((AlarmManager)ApplicationContext.GetSystemService(AlarmService));
var intent2 = new Intent(this, typeof(StepService));
intent2.PutExtra("warning", WarningState);
var stepIntent = PendingIntent.GetService(ApplicationContext, 200, intent2, PendingIntentFlags.UpdateCurrent);
alarmManager.Set(AlarmType.Rtc, Java.Lang.JavaSystem
.CurrentTimeMillis() + 1000 * 60 * 60, stepIntent);
var warning = false;
if (intent != null)
warning = intent.GetBooleanExtra("warning", false);
Startup();
return StartCommandResult.Sticky;
}
public override void OnTaskRemoved(Intent rootIntent)
{
base.OnTaskRemoved(rootIntent);
UnregisterListeners();
var intent = new Intent(this, typeof(StepService));
intent.PutExtra("warning", WarningState);
((AlarmManager)GetSystemService(AlarmService)).Set(AlarmType.Rtc, Java.Lang.JavaSystem
.CurrentTimeMillis() + 500,
PendingIntent.GetService(this, 201, intent, 0));
}
private void Startup(bool warning = false)
{
CrunchDates(true);
if (!isRunning)
{
RegisterListeners();
WarningState = warning;
}
isRunning = true;
}
public override void OnDestroy()
{
base.OnDestroy();
UnregisterListeners();
isRunning = false;
CrunchDates();
}
void RegisterListeners()
{
sManager = GetSystemService(SensorService) as SensorManager;
sManager.RegisterListener(this, sManager.GetDefaultSensor(SensorType.StepCounter), SensorDelay.Ui);
}
void UnregisterListeners()
{
if (!isRunning)
return;
try
{
var sensorManager = (SensorManager)GetSystemService(Context.SensorService);
sensorManager.UnregisterListener(this);
isRunning = false;
}
catch (Exception ex)
{
}
}
StepServiceBinder binder;
public override Android.OS.IBinder OnBind(Android.Content.Intent intent)
{
binder = new StepServiceBinder(this);
return binder;
}
public void OnAccuracyChanged(Sensor sensor, SensorStatus accuracy)
{
//do nothing here
}
public void AddSteps(long count)
{
if (lastSteps == 0)
{
lastSteps = count;
}
newSteps = count - lastSteps;
if (newSteps < 0)
newSteps = 1;
else if (newSteps > 100)
newSteps = 1;
lastSteps = count;
CrunchDates();
Settings.TotalSteps += newSteps;
StepsToday = Settings.TotalSteps - Settings.StepsBeforeToday;
}
long newSteps = 0;
long lastSteps = 0;
public void OnSensorChanged(SensorEvent e)
{
if (lastSteps < 0)
lastSteps = 0;
var count = (long)e.Values[0];
WarningState = false;
AddSteps(count);
}
private void CrunchDates(bool startup = false)
{
if (!Utils.IsSameDay)
{
var yesterday = Settings.CurrentDay;
var dayEntry = StepEntryManager.GetStepEntry(yesterday);
if (dayEntry == null || dayEntry.Date.DayOfYear != yesterday.DayOfYear)
{
dayEntry = new StepEntry();
}
dayEntry.Date = yesterday;
dayEntry.Steps = Settings.CurrentDaySteps;
Settings.CurrentDay = DateTime.Today;
Settings.CurrentDaySteps = 0;
Settings.StepsBeforeToday = Settings.TotalSteps;
StepsToday = 0;
try
{
StepEntryManager.SaveStepEntry(dayEntry);
}
catch (Exception ex)
{
Console.WriteLine("Error {0}", ex.Message);
}
}
else if (startup)
{
StepsToday = Settings.TotalSteps - Settings.StepsBeforeToday;
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name)
{
if (PropertyChanged == null)
return;
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
I am using Onion Architecture with Autofac. In my Dependency Injection Code, I am using:
[assembly: WebActivatorEx.PostApplicationStartMethod(typeof(IocConfig), "RegisterDependencies")]
namespace AppMVC.Infrastructure.Bootstrapper
{
public class IocConfig
{
public static void RegisterDependencies()
{
var builder = new ContainerBuilder();
builder.RegisterType(typeof(UnitOfWork)).As(typeof(IUnitOfWork)).InstancePerHttpRequest();
builder.Register<IEntitiesContext>(b =>
{
var context = new MyContext("My Connection String");
return context;
}).InstancePerHttpRequest();
}
}
}
Unit Of Work Code:
public class UnitOfWork : IUnitOfWork
{
private readonly IEntitiesContext _context;
private bool _disposed;
private Hashtable _repositories;
public UnitOfWork(IEntitiesContext context)
{
_context = context;
}
public int SaveChanges()
{
return _context.SaveChanges();
}
public IRepository<TEntity> Repository<TEntity>() where TEntity : BaseEntity
{
if (_repositories == null)
{
_repositories = new Hashtable();
}
var type = typeof(TEntity).Name;
if (_repositories.ContainsKey(type))
{
return (IRepository<TEntity>)_repositories[type];
}
var repositoryType = typeof(EntityRepository<>);
_repositories.Add(type, Activator.CreateInstance(repositoryType.MakeGenericType(typeof(TEntity)), _context));
return (IRepository<TEntity>)_repositories[type];
}
public void BeginTransaction()
{
_context.BeginTransaction();
}
public int Commit()
{
return _context.Commit();
}
public void Rollback()
{
_context.Rollback();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing)
{
if (!_disposed && disposing)
{
_context.Dispose();
foreach (IDisposable repository in _repositories.Values)
{
repository.Dispose();// dispose all repositries
}
}
_disposed = true;
}
}
MyContext Code:
public class MyContext : DbContext, IEntitiesContext
{
private ObjectContext _objectContext;
private DbTransaction _transaction;
public MyContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
}
public void BeginTransaction()
{
_objectContext = ((IObjectContextAdapter)this).ObjectContext;
if (_objectContext.Connection.State == ConnectionState.Open)
{
if (_transaction == null)
{
_transaction = _objectContext.Connection.BeginTransaction();
}
return;
}
_objectContext.Connection.Open(); // At this Line, I am getting Exception
if (_transaction == null)
{
_transaction = _objectContext.Connection.BeginTransaction();
}
}
public int Commit()
{
var saveChanges = SaveChanges();
_transaction.Commit();
return saveChanges;
}
public void Rollback()
{
_transaction.Rollback();
}
}
My problem is, On _objectContext.Connection.Open();, I am getting Connection String missing error.
Below is the screenshot of the Exception:
I have a CursorLoader that observes a directory with this URI:
uriDirectory = content://com.myapp.stocks/stocks
and another CursorLoader that observes an item with this URI:
uriItem = content://com.myapp.stocks/stocks/GOOG
When I update uriItem and call getContext().getContentResolver().notifyChange(uriItem , null); in my ContentProvider, how can I prevent it from notifying uriDirectory as well?
Thanks!
Edit: So my solution so far is just to have a boolean that is set to true when I notify a uriItem. Then when it notifies the parent, uriDirectory, it will see that the boolean is true and won't perform any operations. After, I set the boolean back to false.
You can write your own CursorLoader. The default cursor loaders register a content observer via Cursor.RegisterContentObserver(ContentObserver observer). Instead, we want to use registerContentObserver(Uri uri, boolean notifyForDescendants, ContentObserver observer).
I'm not sure if you are using the support library CursorLoader but for the greatest applicability, that's what I'm using.
The only changes from the stock android versions are in loadInBackground(). You should create an entire class instead of just extending android's and overriding loadInBackground because it protects you from future changes made to Android. Be advised that this will not use any notification url you set for the cursor in your ContentProvider unless you the device is KitKat or newer
Uri notificationUri;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
notificationUri = cursor.getNotificationUri();
} else {
notificationUri = mUri;
}
getContext().getContentResolver().registerContentObserver(
notificationUri != null ? notificationUri : mUri,
false, //don't notify for descendants
mObserver
);
Full class descendantChangeIgnoringCursorLoader.java:
package com.innomatixdata.busscan.utils;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.ContentResolverCompat;
import android.support.v4.content.Loader;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Arrays;
public class DescendantChangeIgnoringCursorLoader extends AsyncTaskLoader<Cursor> {
final Loader.ForceLoadContentObserver mObserver;
Uri mUri;
String[] mProjection;
String mSelection;
String[] mSelectionArgs;
String mSortOrder;
Cursor mCursor;
android.support.v4.os.CancellationSignal mCancellationSignal;
/* Runs on a worker thread */
#Override
public Cursor loadInBackground() {
synchronized (this) {
if (isLoadInBackgroundCanceled()) {
throw new android.support.v4.os.OperationCanceledException();
}
mCancellationSignal = new android.support.v4.os.CancellationSignal();
}
try {
Cursor cursor = ContentResolverCompat.query(getContext().getContentResolver(),
mUri, mProjection, mSelection, mSelectionArgs, mSortOrder,
mCancellationSignal);
if (cursor != null) {
try {
// Ensure the cursor window is filled.
cursor.getCount();
Uri notificationUri;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
notificationUri = cursor.getNotificationUri();
} else {
notificationUri = mUri;
}
getContext().getContentResolver().registerContentObserver(
notificationUri != null ? notificationUri : mUri,
false, //don't notify for descendants
mObserver
);
} catch (RuntimeException ex) {
cursor.close();
throw ex;
}
}
return cursor;
} finally {
synchronized (this) {
mCancellationSignal = null;
}
}
}
#Override
public void cancelLoadInBackground() {
super.cancelLoadInBackground();
synchronized (this) {
if (mCancellationSignal != null) {
mCancellationSignal.cancel();
}
}
}
/* Runs on the UI thread */
#Override
public void deliverResult(Cursor cursor) {
if (isReset()) {
// An async query came in while the loader is stopped
if (cursor != null) {
cursor.close();
}
return;
}
Cursor oldCursor = mCursor;
mCursor = cursor;
if (isStarted()) {
super.deliverResult(cursor);
}
if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
oldCursor.close();
}
}
/**
* Creates an empty unspecified CursorLoader. You must follow this with
* calls to {#link #setUri(Uri)}, {#link #setSelection(String)}, etc
* to specify the query to perform.
*/
public DescendantChangeIgnoringCursorLoader(Context context) {
super(context);
mObserver = new Loader.ForceLoadContentObserver();
}
/**
* Creates a fully-specified CursorLoader. See {#link ContentResolver#query(Uri, String[],
* String, String[], String) ContentResolver.query()} for documentation on the meaning of the
* parameters. These will be passed as-is to that call.
*/
public DescendantChangeIgnoringCursorLoader(Context context, Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
super(context);
mObserver = new Loader.ForceLoadContentObserver();
mUri = uri;
mProjection = projection;
mSelection = selection;
mSelectionArgs = selectionArgs;
mSortOrder = sortOrder;
}
/**
* Starts an asynchronous load of the contacts list data. When the result is ready the callbacks
* will be called on the UI thread. If a previous load has been completed and is still valid
* the result may be passed to the callbacks immediately.
*
* Must be called from the UI thread
*/
#Override
protected void onStartLoading() {
if (mCursor != null) {
deliverResult(mCursor);
}
if (takeContentChanged() || mCursor == null) {
forceLoad();
}
}
/**
* Must be called from the UI thread
*/
#Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
#Override
public void onCanceled(Cursor cursor) {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
#Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
if (mCursor != null && !mCursor.isClosed()) {
mCursor.close();
}
mCursor = null;
}
public Uri getUri() {
return mUri;
}
public void setUri(Uri uri) {
mUri = uri;
}
public String[] getProjection() {
return mProjection;
}
public void setProjection(String[] projection) {
mProjection = projection;
}
public String getSelection() {
return mSelection;
}
public void setSelection(String selection) {
mSelection = selection;
}
public String[] getSelectionArgs() {
return mSelectionArgs;
}
public void setSelectionArgs(String[] selectionArgs) {
mSelectionArgs = selectionArgs;
}
public String getSortOrder() {
return mSortOrder;
}
public void setSortOrder(String sortOrder) {
mSortOrder = sortOrder;
}
#Override
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
super.dump(prefix, fd, writer, args);
writer.print(prefix); writer.print("mUri="); writer.println(mUri);
writer.print(prefix); writer.print("mProjection=");
writer.println(Arrays.toString(mProjection));
writer.print(prefix); writer.print("mSelection="); writer.println(mSelection);
writer.print(prefix); writer.print("mSelectionArgs=");
writer.println(Arrays.toString(mSelectionArgs));
writer.print(prefix); writer.print("mSortOrder="); writer.println(mSortOrder);
writer.print(prefix); writer.print("mCursor="); writer.println(mCursor);
}
}