Thursday, November 29, 2012

Copy Windows Phone Content To Isolated Storage

Some times a database is deployed with the application as a content file.

However, the database can't be used directly, it must be copied to the storage first.

In this sample code, the content file is copied to the isolated storage if it isn't copied yet.
IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication();
String DBFile = "DB.sqlite";
if (!ISF.FileExists(DBFile)) CopyFromContentToStorage(ISF, "Database/DB.sqlite", DBFile);

private void CopyFromContentToStorage(IsolatedStorageFile ISF, String SourceFile, String DestinationFile)
{
    Stream Stream = Application.GetResourceStream(new Uri(SourceFile, UriKind.Relative)).Stream;
    IsolatedStorageFileStream ISFS = new IsolatedStorageFileStream(DestinationFile, System.IO.FileMode.Create, System.IO.FileAccess.Write, ISF);
    CopyStream(Stream, ISFS);
    ISFS.Flush();
    ISFS.Close();
    Stream.Close();
    ISFS.Dispose();
}
private void CopyStream(Stream Input, IsolatedStorageFileStream Output)
{
    Byte[] Buffer = new Byte[5120];
    Int32 ReadCount = Input.Read(Buffer, 0, Buffer.Length);
    while (ReadCount > 0)
    {
        Output.Write(Buffer, 0, ReadCount);
        ReadCount = Input.Read(Buffer, 0, Buffer.Length);
    }
}
The code assumes that the file to be copied is named 'DB.sqlite' that resides in a folder named 'database' and was added to the project as a content file.

Copy Android Asset To Internal Storage

Some times a database is deployed with the application as an asset.

However, the database can't be used directly, it must be copied to the storage first.

In this sample code, the asset is copied to the internal storage if it isn't copied yet.
Context Context = getApplicationContext();
String DestinationFile = Context.getFilesDir().getPath() + File.separator + "DB.sqlite";
if (!new File(DestinationFile).exists()) {
  try {
    CopyFromAssetsToStorage(Context, "Database/DB.sqlite", DestinationFile);
  } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
  }
}

private void CopyFromAssetsToStorage(Context Context, String SourceFile, String DestinationFile) throws IOException {
  InputStream IS = Context.getAssets().open(SourceFile);
  OutputStream OS = new FileOutputStream(DestinationFile);
  CopyStream(IS, OS);
  OS.flush();
  OS.close();
  IS.close();
}
private void CopyStream(InputStream Input, OutputStream Output) throws IOException {
  byte[] buffer = new byte[5120];
  int length = Input.read(buffer);
  while (length > 0) {
    Output.write(buffer, 0, length);
    length = Input.read(buffer);
  }
}
The code assumes that the file to be copied is named 'DB.sqlite' and it resides in a folder named 'database' in the assets.

Wednesday, November 28, 2012

Start Thread On Android

You can start a new thread by extending the Thread class or implementing the Runnable interface.

Extending the Thread class:
Thread T = new NewThread();
T.start();

private class NewThread extends Thread {
  @Override
  public void run() {
    //Your asynchronous code
  }
}
Implementing the Runnable interface:
Thread T = new Thread(new NewRunnable());
T.start();

private class NewRunnable implements Runnable {
  public void run() {
    //Your asynchronous code
  }
}
Your activity may implement the Runnable interface directly.
In this case, when creating the Thread object you must pass the activity (this) as the parameter.

Wednesday, November 21, 2012

Prevent Android UI Resize When Keyboard Opens

An android activity may be resized when the soft keyboard opens.

Sometimes that's not the behavior we want.

To disable the resizing, add the following line to the activity declaration on the manifest:

If the UI contains a ScrollView, then you can also add the following to the view declaration to prevent the resizing:
android:isScrollContainer="false" 

Thursday, November 8, 2012

Update Android UI From Other Threads

Asynchronous functions are useful to run code in background so the UI will not freeze.

Those functions can't access the UI directly because they aren't running in the UI thread.

If you try to access the UI from those threads you will get the error:
"Only the original thread that created a view hierarchy can touch its views."

The solutions is to use Handlers.
private Handler YOURHANDLER = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        //do some code in the UI thread
    }
};

public void ASYNCHRONOUSFUNCTION() {
    Message Msg = new Message();
    Msg.obj = "SOME TEXT"; //can be any object
    YOURHANDLER.sendMessage(Msg);
}
In the example, the ASYNCHRONOUSFUNCTION function runs in another thread.

The Message object will contain any information in it's obj property that you want to send to the handler.

Finally, you invoke the sendMessage method of the YOURHANDLER handler.

Programmatically Hide Android SIP

Some times we want to programmatically hide the virtual keyboard (SIP, soft input panel).

This is how you do it:
InputMethodManager IMM = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 
IMM.hideSoftInputFromWindow(v.getWindowToken(), 0);
In the code, the V variable may represent any view of the activity.

Friday, October 26, 2012

Force Windows Phone Theme

Windows Phone applications inherits the theme of the OS on launch.

When the UI is designed specially for the dark theme it won't look well on the light theme, or vice versa.

To prevent this the application can force the default dark or light theme.

In the application class' constructor put this code to force the dark theme:
if ((Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible) MergeCustomColors("/Themes/DarkStyles.xaml");
Or this code to force the light theme:
if ((Visibility)Application.Current.Resources["PhoneDarkThemeVisibility"] == Visibility.Visible) MergeCustomColors("/Themes/LightStyles.xaml");
Anywhere in your project put this method:
private void MergeCustomColors(String Theme)
{
    ResourceDictionary Dictionaries = new ResourceDictionary();
    String source = String.Format(Theme);
    var themeStyles = new ResourceDictionary { Source = new Uri(source, UriKind.Relative) };
    Dictionaries.MergedDictionaries.Add(themeStyles);
    ResourceDictionary appResources = Current.Resources;
    foreach (DictionaryEntry entry in Dictionaries.MergedDictionaries[0])
    {
        SolidColorBrush ColorBrush = entry.Value as SolidColorBrush;
        SolidColorBrush ExistingBrush = appResources[entry.Key] as SolidColorBrush;
        if (ExistingBrush != null && ColorBrush != null) { ExistingBrush.Color = ColorBrush.Color; }
    }
}
The code assumes that the projects contains the files DarkStyles.xaml and LightStyles.xaml in a folder named Themes.

A demo project can be found here.

Get Windows Phone Accent Color

Some times an application needs to know which accent color is currently in use on the device so it can adjust it's UI.

The PhoneAccentColor key indicates the accent color as a Color object.
The PhoneAccentBrush key indicates the accent color as a Brush object.

In XAML you can do something like:
<TextBlock Foreground="{StaticResource PhoneAccentBrush}" />
<Border>
  <Border.Background>
    <SolidColorBrush Color="{StaticResource PhoneAccentColor}" />
  </Border.Background>
</Border>
In C#:
Color AccentColor = (Color)Resources["PhoneAccentColor"];
Brush AccentBrush = (Brush)Resources["PhoneAccentBrush"];

Detect Windows Phone Theme

Some times an application needs to know which theme is currently in use on the device so it can adjust it's UI.

The PhoneLightThemeVisibility key indicates the visibility of the light theme.
The PhoneDarkThemeVisibility key indicates the visibility of the dark theme.

In XAML you can do something like:
<TextBlock Visibility="{StaticResource PhoneLightThemeVisibility}" />
<TextBlock Visibility="{StaticResource PhoneDarkThemeVisibility}" />
You can use a converter to manipulate other properties that are not of type Visibility.

In C#:
Visibility LightThemeVisibility = (Visibility)Resources["PhoneLightThemeVisibility"];
Visibility DarkThemeVisibility = (Visibility)Resources["PhoneDarkThemeVisibility"];

Thursday, October 25, 2012

Windows Phone Flip Animation

You can use the Projection class to produce the flip animation of a control.

The following XAML ilustrates this:
<UserControl.Resources>
    <Storyboard x:FieldModifier="private" x:Name="SBStartAnimation">
        <DoubleAnimation Storyboard.TargetName="SPPanel" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)" From="-90" To="0" Duration="0:0:0.150" />
    </Storyboard>
</UserControl.Resources>

<Border x:FieldModifier="private" x:Name="BShade" Background="#aa000000">
    <StackPanel x:FieldModifier="private" x:Name="SPPanel" VerticalAlignment="Top" Background="#222222">
        <StackPanel.Projection> 
            <PlaneProjection CenterOfRotationY="0.5" RotationX="0" /> 
         </StackPanel.Projection> 
        <Image Source="/Background.png" HorizontalAlignment="Center" Stretch="None" />
        <LC:ProgressLine x:FieldModifier="private" x:Name="PLProgress" Margin="0,-5,0,10" /> 
        <TextBlock Text="Working, please wait..." HorizontalAlignment="Center" Margin="0,0,0,20" /> 
    </StackPanel>
</Border> 
The SPPanel Stackpanel is flipped as defined in the SBStartAnimation Storyboard.