Android

Uit Wiki Durk 'o' Theek
Versie door Durkio (Overleg | bijdragen) op 7 jul 2013 om 00:09

Ga naar: navigatie, zoeken

Programma kunnen verplaatsen naar een SD-kaart, artikel afkomstig van TechRepublic


By Chris Duckett July 2, 2013, 10:18 PM PDT Takeaway: A simple line in your Android app’s manifest can save much user frustration.

When people do not grok Android, and then go about making apps, it often shows.

Unless an application is a vital system replacement, such as a keyboard, or is a Service, then there really is no reason why an application cannot reside on an Android device’s external storage, if it exists. (A full caveat list for not installing on external storage can be http://developer.android.com/guide/topics/data/install-location.html#ShouldNot found here].)

As the years have gone by, this inability of many applications to allow movement to external storage has become quite frustrating — and it all extends from a quirk of Android device designs’ past.

If you have only experienced an Android phone that has been released in the past two years, then you would not have come across the feature called “internal storage”.

Take the Samsung Galaxy S2, for example: Even though a phone is advertised with 16GB of internal storage, 2GB of that storage is claimed by Android for “system” purposes, leaving the rest for the user to do whatever they like with.

Sometimes, though, much of the free space on the internal storage is claimed by log or tombstone files that can eat away at the storage until users can no longer install apps without an error.

Even though the user’s SD card and USB storage (what the rest of the un-system internal storage is called) may have gigabytes free, an amount of internal storage is needed to install or update apps. The result is that users end up in a dreaded place where an “Insufficient storage available” error occurs when trying to install/upgrade an application — all because that internal storage is under root control and cannot be cleared out by your average user.

A factory reset or rooting the phone are ways to get the internal storage back under control, but the average user will not do these things.

One way to help them out is to set the "installLocation property" in your Android app’s manifest.

By default, Android picks a value of “internalOnly”, which forces applications to be installed onto internal storage, and to never be installed on external storage. If the internal storage is full, it will not install or update the app.

This is an approach that will have your app cursed and sworn at when it takes up a Vine-like 50MB of precious space and refuses to be moved to external storage.

Therefore, for most apps, you should set the installLocation property, and set it to “auto” or “preferExternal”. The former will target internal storage first, but allow movement to the external storage later on; the latter will aim at external storage first, and fall back to internal if needed.

It’s a simple one line, but it can help a frustrated Android owner either clear some storage space or avoid your app being uninstalled in a vicious cycle of uninstalling to clean up a phone’s internal memory.



SMS versturen vanuit je App, artikel afkomstig van TechRepublic

One thing Android does well is allow developers to interact with the phone. Between the TelephonyManager and the SmsManager, the Android SDK usually has you covered. In the tutorial that follows, we will send a text message directly from within our application. Best of all, thanks to the SmsManager, the code that does the actual transmission of the SMS message fits on a single line.

Feel free to follow along with the step-by-step instructions below, or, download the entire project and import it directly into Eclipse.

1. Create a new Android project in Eclipse. Target Android 2.2 or higher.

2. In order to send a text message from an application, the manifest must declare the SEND_SMS permission. Open the AndroidManifest.xml and add the permission just after the SDK declarations.

AndroidManifest.xml

<?xml version=<em>"1.0"</em> encoding=<em>"utf-8"</em>?>
<manifest xmlns:android=<em>"http://schemas.android.com/apk/res/android"
</em>    package=<em>"com.authorwjf.hellosms"
</em>    android:versionCode=<em>"1"
</em>    android:versionName=<em>"1.0"</em> >
    <uses-sdk
        android:minSdkVersion=<em>"8"
</em>        android:targetSdkVersion=<em>"17"</em> />
    <uses-permission android:name=<em>"android.permission.SEND_SMS"</em> />
    <application
        android:allowBackup=<em>"true"
</em>        android:icon=<em>"@drawable/ic_launcher"
</em>        android:label=<em>"@string/app_name"
</em>        android:theme=<em>"@style/AppTheme"</em> >
        <activity
            android:name=<em>"com.authorwjf.hellosms.MainActivity"
</em>            android:label=<em>"@string/app_name"</em> >
            <intent-filter>
                <action android:name=<em>"android.intent.action.MAIN"</em> />
                <category android:name=<em>"android.intent.category.LAUNCHER"</em> />
            </intent-filter>
        </activity>
    </application>
</manifest>

3. In the /res/layout folder, create a new linear layout to represent our user interface. We need a text view, edit text, and a button.

activity_main.xml

<LinearLayout xmlns:android=<em>"http://schemas.android.com/apk/res/android"
</em>    android:layout_width=<em>"fill_parent"
</em>    android:layout_height=<em>"fill_parent"
</em>    android:orientation=<em>"vertical"
</em>    android:gravity=<em>"center"
</em>    android:layout_margin=<em>"10dip"</em>>
  <TextView
        android:id=<em>"@+id/textView1"
</em>        android:layout_width=<em>"wrap_content"
</em>        android:layout_height=<em>"wrap_content"
</em>        <span style="text-decoration: underline;">android:text=</span><em><span style="text-decoration: underline;">"Enter A Phone Number:"</span><span style="text-decoration: underline;">
</span></em>        android:textSize=<em>"20sp"</em> />
<span style="text-decoration: underline;">
</span>
  <span style="text-decoration: underline;"><EditText</span><span style="text-decoration: underline;">
</span>      android:id=<em>"@+id/editView1"
</em>      android:layout_width=<em>"fill_parent"
</em>      android:layout_height=<em>"wrap_content"
</em>      android:layout_margin=<em>"20dip"</em> />
   <Button
       android:id=<em>"@+id/button1"
</em>       android:layout_width=<em>"wrap_content"
</em>       android:layout_height=<em>"wrap_content"
</em>       <span style="text-decoration: underline;">android:text=<em>"Say Hello!"</em></span> />
</LinearLayout>

4. Now it is time to modify the MainActivity.java source file. Use the onCreate to wire up the button and implement an onClick override to engage the SmsManager. Check out the call to the SmsManager inside of our try / catch block. As promised, a single line of code is all it takes to send the text message to the destination of your choosing.

MainActivity.java
package com.authorwjf.hellosms;

<strong>import</strong> android.os.Bundle;
<strong>import</strong> android.telephony.SmsManager;
<strong>import</strong> android.view.View;
<strong>import</strong> android.view.View.OnClickListener;
<strong>import</strong> android.widget.EditText;
<strong>import</strong> android.app.Activity;
<strong>import</strong> android.app.AlertDialog;
<strong>public</strong> <strong>class</strong> MainActivity <strong>extends</strong> Activity <strong>implements</strong> OnClickListener{
       @Override
<strong>       protected</strong> <strong>void</strong> onCreate(Bundle savedInstanceState) {
<strong>             super</strong>.onCreate(savedInstanceState);
             setContentView(R.layout.<em>activity_main</em>);
             findViewById(R.id.<em>button1</em>).setOnClickListener(<strong>this</strong>);
       }
       @Override
<strong>       public</strong> <strong>void</strong> onClick(View v) {
             String phoneNumber = ((EditText)
findViewById(R.id.<em>editView1</em>)).getText().toString();
<strong>               try</strong> {
                      SmsManager.<em>getDefault</em>().sendTextMessage(phoneNumber, <strong>null</strong>, "Hello
SMS!", <strong>null</strong>, <strong>null</strong>);
              } <strong>catch</strong> (Exception e) {
                     AlertDialog.Builder alertDialogBuilder = <strong>new</strong>
AlertDialog.Builder(<strong>this</strong>);
                      AlertDialog dialog = alertDialogBuilder.create();
                      dialog.setMessage(e.getMessage());
                      dialog.show();
               }
       }
}

The code is ready to compile and run (Figure A). While it runs on the emulator, you need to load it to an actual device to send an SMS message. Type your own phone number into the text field and say hello to yourself.

Figure A

[1]

[img]http://i.techrepublic.com.com/blogs/8675309.png[/img]

While at first glance, it may seem curious that you’d want your app to send a text message at all when a perfectly good text application ships with the operating system, there are quite a few valid scenarios for using the SmsManager. I use this capability as an easy way for users to recommend my app to their friends. As long as you are careful not to abuse the privilege, text messages are a powerful way to spread the word about your app.


Scale animatie om een 3D flip te simuleren, artikel afkomstig van Techrepublic

If you read my blog posts very often, you know one of the things I like to do when I’m off from my day gig as a mobile consultant is to play around with Android’s animation classes. Last year my 15-year-old son and I wrote a game, and now we are putting the finishing touches on a follow-up title.

As part of our most recent endeavor, we needed to “flip” a tile over when the user tapped on it. The desired effect is similar to that of turning over a playing card, where all the backs look the same, but each face is unique. I began googling Android 3D animations thinking there would be a simple way to pull off the effect using XML transformations and listeners.

Unfortunately, what I found is that to do a “true” 3D flip animation means busting out the android.graphics.Camera package. It requires a matrix, pre and post translations, your own runnable, and a decent amount of the “M” word…math.

Not wanting to get bogged down with a task I’d expected to take no more than a few minutes, I decided for grins I’d try simulating what I was looking for using a simple xScale translation. I didn’t have high hopes, but to my delight the resulting animation wasn’t half bad (fair to Midland as we say here in Texas). In fact, after a bit of tweaking it actually turned our pretty well!

The tutorial that follows will demonstrate how you can use this simple technique in your own applications. Feel free to follow along or download and import the entire project directly into Eclipse.

1. Create a new Android application in Eclipse. Target Android 2.2 or higher.

2. Create a new folder under/res called /drawable. This is where we will store our card front and back images as PNGs.

<a href="http://i.techrepublic.com.com/blogs/card_back.png"><img class="alignleft size-full wp-image-2789" title="card_back" src="http://i.techrepublic.com.com/blogs/card_back.png" alt="" width="155" height="225"></a>

[2][img]http://i.techrepublic.com.com/blogs/card_front2.png[/img]

3. While we are still in the /res directory, add another folder called /anim. Here we will include two XML files representing our two transitional animations.

to_middle.xml

<?xml version=<em>"1.0"</em> encoding=<em>"utf-8"</em>?>
<scale
    xmlns:android=<em>"http://schemas.android.com/apk/res/android"</em>
       android:fromXScale=<em>"1.0"</em> android:toXScale=<em>"0.0"</em>
       android:pivotX=<em>"50%"</em>
       android:fromYScale=<em>"1.0"</em> android:toYScale=<em>"1.0"</em>
       android:pivotY=<em>"50%"</em>
       android:duration=<em>"250"</em> />
from_middle.xml
<?xml version=<em>"1.0"</em> encoding=<em>"utf-8"</em>?>
<scale
    xmlns:android=<em>"http://schemas.android.com/apk/res/android"</em>
<em>       </em>android:fromXScale=<em>"0.0"</em> android:toXScale=<em>"1.0"</em>
<em>       </em>android:pivotX=<em>"50%"</em>
       android:fromYScale=<em>"1.0"</em> android:toYScale=<em>"1.0"</em>
       android:pivotY=<em>"50%"</em>
<em>       </em>android:duration=<em>"250"</em> />

4. Because this is a graphics intensive application, one in which we expect the orientation to be maintained throughout, we will open up the AndroidManifest.xml and add the android:screenOrientation=”portrait” flag to our main activity.

AndroidManifest.xml

<?xml version=<em>"1.0"</em> encoding=<em>"utf-8"</em>?>
<manifest xmlns:android=<em>"http://schemas.android.com/apk/res/android"</em>
    package=<em>"com.authorwjf.deal"</em>
    android:versionCode=<em>"1"</em>
    android:versionName=<em>"1.0"</em> >
    <uses-sdk
        android:minSdkVersion=<em>"8"</em>
        android:targetSdkVersion=<em>"17"</em> />
    <application
        android:allowBackup=<em>"true"</em>
        android:icon=<em>"@drawable/ic_launcher"</em>
        android:label=<em>"@string/app_name"</em>
        android:theme=<em>"@style/AppTheme"</em> >
        <activity
            android:name=<em>"com.authorwjf.deal.MainActivity"</em>
            android:label=<em>"@string/app_name"</em>
            android:screenOrientation=<em>"portrait"</em>>
            <intent-filter>
                <action android:name=<em>"android.intent.action.MAIN"</em> />
                <category android:name=<em>"android.intent.category.LAUNCHER"</em> />
             </intent-filter>
          </activity>
      </application>
</manifest>

5. In the /res/layout folder, we define the activity as a linear layout with a label, image view, and button all stacked vertically.

activity_main.xml

<LinearLayout xmlns:android=<em>"http://schemas.android.com/apk/res/android"</em>
    android:layout_width=<em>"fill_parent"</em>
    android:layout_height=<em>"fill_parent"</em>
    android:orientation = <em>"vertical"</em>
    android:background=<em>"#006600"</em>
    android:gravity = <em>"center"</em>>
    <TextView
        android:id=<em>"@+id/textView1"</em>
        android:layout_width=<em>"wrap_content"</em>
        android:layout_height=<em>"wrap_content"</em>
        <span style="text-decoration: underline;">android:text=<em>"Simulated Card Deal"</em></span>
        android:textColor=<em>"#ffffff"</em>
        android:textSize=<em>"26sp"</em>
        android:layout_margin=<em>"10dip"</em>
        android:textStyle=<em>"bold"</em> />
    <span style="text-decoration: underline;"><ImageView</span>
        android:id=<em>"@+id/imageView1"</em>
        android:layout_width=<em>"wrap_content"</em>
        android:layout_height=<em>"wrap_content"</em>
        android:layout_margin=<em>"10dip"</em>
        android:gravity=<em>"center"</em>
        android:src=<em>"@drawable/card_back"</em> />
    <Button
       android:id=<em>"@+id/button1"</em>
       android:layout_width=<em>"wrap_content"</em>
       android:layout_height=<em>"wrap_content"</em>
       android:layout_margin=<em>"10dip"</em>
       android:padding=<em>"10dip"</em>
       <span style="text-decoration: underline;">android:text=<em>"Hit Me!"</em></span> />
</LinearLayout>

6. It’s time to code up our /src/MainActivity.java file. The majority of the code just handles applying our animations and swapping the images between the front and the back of the card when required.

MainActivity.java

<strong>package</strong> com.authorwjf.deal;
<strong>import</strong> android.os.Bundle;
<strong>import</strong> android.view.View;
<strong>import</strong> android.view.View.OnClickListener;
<strong>import</strong> android.view.animation.Animation;
<strong>import</strong> android.view.animation.Animation.AnimationListener;
<strong>import</strong> android.view.animation.AnimationUtils;
<strong>import</strong> android.widget.ImageView;
<strong>import</strong> android.app.Activity;
<strong>public</strong> <strong>class</strong> MainActivity <strong>extends</strong> Activity <strong>implements</strong> OnClickListener,
AnimationListener {
<strong>
</strong>
<strong>       private</strong> Animation animation1;
<strong>       private</strong> Animation animation2;
<strong>       private</strong> <strong>boolean</strong> isBackOfCardShowing = <strong>true</strong>;
       @Override
<strong>       protected</strong> <strong>void</strong> onCreate(Bundle savedInstanceState) {
<strong>             super</strong>.onCreate(savedInstanceState);
             setContentView(R.layout.<em>activity_main</em>);
             animation1 = AnimationUtils.<em>loadAnimation</em>(<strong>this</strong>, R.anim.<em>to_middle</em>);
             animation1.setAnimationListener(<strong>this</strong>);
             animation2 = AnimationUtils.<em>loadAnimation</em>(<strong>this</strong>, R.anim.<em>from_middle</em>);
             animation2.setAnimationListener(<strong>this</strong>);
             findViewById(R.id.<em>button1</em>).setOnClickListener(<strong>this</strong>);
       }
       @Override
<strong>       public</strong> <strong>void</strong> onClick(View v) {
              v.setEnabled(<strong>false</strong>);
              ((ImageView)findViewById(R.id.<em>imageView1</em>)).clearAnimation();
              ((ImageView)findViewById(R.id.<em>imageView1</em>)).setAnimation(animation1);
              ((ImageView)findViewById(R.id.<em>imageView1</em>)).startAnimation(animation1);
        }
        @Override
<strong>        public</strong> <strong>void</strong> onAnimationEnd(Animation animation) {
<strong>              if</strong> (animation==animation1) {
<strong>                     if</strong> (isBackOfCardShowing) {
        ((ImageView)findViewById(R.id.<em>imageView1</em>)).setImageResource(R.drawable.<em>card_front</em>);
                       } <strong>else</strong> {
        ((ImageView)findViewById(R.id.<em>imageView1</em>)).setImageResource(R.drawable.<em>card_back</em>);
                       }
                       ((ImageView)findViewById(R.id.<em>imageView1</em>)).clearAnimation();
         ((ImageView)findViewById(R.id.<em>imageView1</em>)).setAnimation(animation2);
         ((ImageView)findViewById(R.id.<em>imageView1</em>)).startAnimation(animation2);
                 } <strong>else</strong> {
                        isBackOfCardShowing=!isBackOfCardShowing;
                        findViewById(R.id.<em>button1</em>).setEnabled(<strong>true</strong>);
                 }
        }
        @Override
<strong>        public</strong> <strong>void</strong> onAnimationRepeat(Animation animation) {
               // <strong>TODO</strong> Auto-generated method stub
        }
        @Override
<strong>        public</strong> <strong>void</strong> onAnimationStart(Animation animation) {
        // <strong>TODO</strong> Auto-generated method stub
        }
}

Ready to give it a try? Load the APK onto an emulator or device and click the button to deal up the face down card.

[3][img]http://i.techrepublic.com.com/blogs/deal_card.png[/img]

Something interesting I discovered while experimenting with the to/from xml files is that even though the Y scale doesn’t change, you must include a 1.0 start and finish value for it; otherwise, the animation fails to render with no indication as to why.