分类目录归档:Android

Android service 自动重启

当Android的service被停止(内存不够、被其他app杀掉)的时候,加入以下代码到你的service里,就可以马上重新启动了。

@Override
public void onDestroy() {
  super.onDestroy();
  // Restart service in 500 ms
  ((AlarmManager) getSystemService(Context.ALARM_SERVICE))
  .set(AlarmManager.RTC,
    System.currentTimeMillis() + 500,
    PendingIntent.getService(this, 3, new Intent(this, TaskService.class), 0));
}

Android:通过Url打开App

Android支持通过Url打开App,比如下面的Url
scheme://host/datastring
要打开这样的Url,首先在配置文件AndroidManifest.xml里使用<data>添加一种App打开的格式,代码如下

<?xml version=”1.0″ encoding=”utf-8″?>
<manifest xmlns:android=”http://schemas.android.com/apk/res/android”
  package=”com.sheng00.customuridemo”
  android:versionCode=”1″
  android:versionName=”1.0″ >
  <uses-sdk
    android:minSdkVersion=”9″
    android:targetSdkVersion=”17″ />
  <application
    android:allowBackup=”true”
    android:icon=”@drawable/ic_launcher”
    android:label=”@string/app_name”
    android:theme=”@style/AppTheme” >
    <activity
      android:name=”com.sheng00.customuridemo.MainActivity”
      android:label=”@string/app_name” >
      <intent-filter>
        <action android:name=”android.intent.action.MAIN” />
        <category android:name=”android.intent.category.LAUNCHER” />
      </intent-filter>
      <!– Open links like scheme://host/?… –>
      <intent-filter>
        <action android:name=”android.intent.action.VIEW” />
        <category android:name=”android.intent.category.DEFAULT” />
        <category android:name=”android.intent.category.BROWSABLE” />
        <data android:scheme=”scheme” android:host=”host” />
      </intent-filter>
    </activity>
  </application>
</manifest>

注意,第二个<intent-filter>中的data绑定了url 在页面中出现scheme://host/类似这样的链接,点击就可以直接打开app app中处理链接地址代码如下

package com.sheng00.customuridemo;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.widget.TextView;
public class MainActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
  }
  @Override
  protected void onResume() {
    super.onResume();
    Intent intent = getIntent();
    if (intent != null) {
      String action = intent.getAction();
      String dataString = intent.getDataString();
      if(dataString!=null){
        TextView tv = (TextView) findViewById(R.id.tv);
        tv.append("n" + dataString);
      }
    }
  }
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
  }
}

运行效果
运行效果

源代码:https://github.com/shengoo/myandroidcode/tree/master/CustomUriDemo

Customized SeekBarPreference

Android没有提供SeekBarPreference,所以只有自己写一个了。。

SeekBarPreference.java

package com.sheng00.BatteryStatus;
import com.sheng00.BattaryStatus.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.preference.Preference;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
public class SeekBarPreference extends Preference implements OnSeekBarChangeListener {
    private final String TAG = getClass().getName();
    private static final String ANDROIDNS="http://schemas.android.com/apk/res/android";
    private static final String SHENG00NS="http://sheng00.com";
    private static final int DEFAULT_VALUE = 50;
    private int mMaxValue      = 100;
    private int mMinValue      = 0;
    private int mInterval      = 1;
    private int mCurrentValue;
    private String mUnitsLeft  = "";
    private String mUnitsRight = "";
    private SeekBar mSeekBar;
    private TextView mStatusText;
    public SeekBarPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        initPreference(context, attrs);
    }
    public SeekBarPreference(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initPreference(context, attrs);
    }
    private void initPreference(Context context, AttributeSet attrs) {
        setValuesFromXml(attrs);
        mSeekBar = new SeekBar(context, attrs);
        mSeekBar.setOnSeekBarChangeListener(this);
        mSeekBar.setMax(mMaxValue - mMinValue);
    }
    private void setValuesFromXml(AttributeSet attrs) {
        mMaxValue = attrs.getAttributeIntValue(ANDROIDNS, "max", 100);
        mMinValue = attrs.getAttributeIntValue(SHENG00NS, "min", 0);
        mUnitsLeft = getAttributeStringValue(attrs, SHENG00NS, "unitsLeft", "");
        String units = getAttributeStringValue(attrs, SHENG00NS, "units", "");
        mUnitsRight = getAttributeStringValue(attrs, SHENG00NS, "unitsRight", units);
        try {
            String newInterval = attrs.getAttributeValue(SHENG00NS, "interval");
            if(newInterval != null)
                mInterval = Integer.parseInt(newInterval);
        }
        catch(Exception e) {
            Log.e(TAG, "Invalid interval value", e);
        }
    }
    private String getAttributeStringValue(AttributeSet attrs, String namespace, String name, String defaultValue) {
        String value = attrs.getAttributeValue(namespace, name);
        if(value == null)
            value = defaultValue;
        return value;
    }
    @Override
    protected View onCreateView(ViewGroup parent){
        RelativeLayout layout =  null;
        try {
            LayoutInflater mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            layout = (RelativeLayout)mInflater.inflate(R.layout.seek_bar_preference, parent, false);
        }
        catch(Exception e)
        {
            Log.e(TAG, "Error creating seek bar preference", e);
        }
        return layout;
    }
    @Override
    public void onBindView(View view) {
        super.onBindView(view);
        try
        {
            // move our seekbar to the new view we've been given
            ViewParent oldContainer = mSeekBar.getParent();
            ViewGroup newContainer = (ViewGroup) view.findViewById(R.id.seekBarPrefBarContainer);
            if (oldContainer != newContainer) {
                // remove the seekbar from the old view
                if (oldContainer != null) {
                    ((ViewGroup) oldContainer).removeView(mSeekBar);
                }
                // remove the existing seekbar (there may not be one) and add ours
                newContainer.removeAllViews();
                newContainer.addView(mSeekBar, ViewGroup.LayoutParams.FILL_PARENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT);
            }
        }
        catch(Exception ex) {
            Log.e(TAG, "Error binding view: " + ex.toString());
        }
        updateView(view);
    }
    /**
     * Update a SeekBarPreference view with our current state
     * @param view
     */
    protected void updateView(View view) {
        try {
            RelativeLayout layout = (RelativeLayout)view;
            mStatusText = (TextView)layout.findViewById(R.id.seekBarPrefValue);
            mStatusText.setText(String.valueOf(mCurrentValue));
            mStatusText.setMinimumWidth(30);
            mSeekBar.setProgress(mCurrentValue - mMinValue);
            mSeekBar.setEnabled(this.isEnabled());
            TextView unitsRight = (TextView)layout.findViewById(R.id.seekBarPrefUnitsRight);
            unitsRight.setText(mUnitsRight);
            TextView unitsLeft = (TextView)layout.findViewById(R.id.seekBarPrefUnitsLeft);
            unitsLeft.setText(mUnitsLeft);
        }
        catch(Exception e) {
            Log.e(TAG, "Error updating seek bar preference", e);
        }
    }
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        int newValue = progress + mMinValue;
        if(newValue > mMaxValue)
            newValue = mMaxValue;
        else if(newValue < mMinValue)
            newValue = mMinValue;
        else if(mInterval != 1 && newValue % mInterval != 0)
            newValue = Math.round(((float)newValue)/mInterval)*mInterval;
        // change rejected, revert to the previous value
        if(!callChangeListener(newValue)){
            seekBar.setProgress(mCurrentValue - mMinValue);
            return;
        }
        // change accepted, store it
        mCurrentValue = newValue;
        if (mStatusText != null) {
            mStatusText.setText(String.valueOf(newValue));
        }
        persistInt(newValue);
    }
    public void onStartTrackingTouch(SeekBar seekBar) {}
    public void onStopTrackingTouch(SeekBar seekBar) {
        notifyChanged();
    }
    @Override
    protected Object onGetDefaultValue(TypedArray ta, int index){
        int defaultValue = ta.getInt(index, DEFAULT_VALUE);
        return defaultValue;
    }
    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
        if(restoreValue) {
            mCurrentValue = getPersistedInt(mCurrentValue);
        }
        else {
            int temp = 0;
            try {
                temp = (Integer)defaultValue;
            }
            catch(Exception ex) {
                Log.e(TAG, "Invalid default value: " + defaultValue.toString());
            }
            persistInt(temp);
            mCurrentValue = temp;
        }
    }
}

这时需要在layout里写布局文件
seek_bar_preference.xml

<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@android:id/widget_frame"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:paddingLeft="15dp"
  android:paddingTop="5dp"
  android:paddingRight="10dp"
  android:paddingBottom="5dp"
  >
  <TextView android:id="@android:id/title"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textSize="22dp"
    android:typeface="sans"
    android:textStyle="normal"
    android:textColor="#ffffff"
  ></TextView>
  <TextView android:id="@android:id/summary"
    android:layout_alignParentLeft="true"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_below="@android:id/title"
  ></TextView>
  <TextView android:id="@+id/seekBarPrefUnitsRight"
    android:layout_alignParentRight="true"
    android:layout_below="@android:id/title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
  ></TextView>
  <TextView android:id="@+id/seekBarPrefValue"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toLeftOf="@id/seekBarPrefUnitsRight"
    android:layout_below="@android:id/title"
    android:gravity="right"
  ></TextView>
  <TextView android:id="@+id/seekBarPrefUnitsLeft"
    android:layout_below="@android:id/title"
    android:layout_toLeftOf="@id/seekBarPrefValue"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
  ></TextView>
  <LinearLayout android:id="@+id/seekBarPrefBarContainer"
    android:layout_alignParentLeft="true"
    android:layout_alignParentBottom="true"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_below="@android:id/summary">
  </LinearLayout>
</RelativeLayout>

然后可以写进我们的activity的布局文件里了:

<com.sheng00.batterystatus.seekbarpreference
  sheng00:unitsright="%"
  sheng00:unitsleft=""
  android:dependency="@string/low_alert_checkbox"
  android:summary=" "
  android:title="@string/low_alert_level"
  sheng00:min="1"
  android:max="50"
  android:key="@string/low_alert_level_key"
  android:defaultvalue="15" />

效果如下图:
device-2011-12-21-115808

android.intent.action.MAIN与android.intent.category的作用

在android和ophone的应用程序可以有多个Activity,每个Activity是同级别的,那么在启动程序时,最先启动哪个Activity呢?

有些程序可能需要显示在程序列表里,有些不需要。怎么定义呢?

android.intent.action.MAIN决定应用程序最先启动的Activity 。
android.intent.category.LAUNCHER决定应用程序是否显示在程序列表里。

因为你的程序可能有很多个activity,
只要xml配置文件中有这么一个intent-filter,而且里面有这个launcher,那么这个activity就是点击程序时最先运行的那个activity。

如果只有一个Activity,没有这两句也可以。

android 程序设置全屏显示

2中方法

 

在AndroidManifest.xml中

<activity android:name=””

android:theme=”@android:style/Theme.NoTitleBar.Fullscreen”/>

 

程序里

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

android sdk下载地址

ADT 10.0.0下载地址

http://dl.google.com/android/ADT-10.0.0.zip

 

下载下列文件时加前缀 
https://dl-ssl.google.com/android/repository/

API 2
android-1.1_r1-windows.zip
android-1.1_r1-macosx.zip
android-1.1_r1-linux.zip

API 3
android-1.5_r03-windows.zip
android-1.5_r03-linux_x86.zip
android-1.5_r03-mac_x86.zip
google_apis-3-r03.zip 

API 4
android-1.6_r02-windows.zip
android-1.6_r02-linux.zip
android-1.6_r02-macosx.zip
google_apis-4_r02.zip

API 5
android-2.0_r01-windows.zip
android-2.0_r01-linux.zip
android-2.0_r01-macosx.zip
google_apis-5_r01.zip

API 6
android-2.0.1_r01-linux.zip
android-2.0.1_r01-macosx.zip
android-2.0.1_r01-windows.zip
google_apis-6_r01.zip

API 7
android-2.1_r01-windows.zip
samples-2.1_r01-linux.zip
android-2.1_r01-macosx.zip
google_apis-7_r01.zip

 

API 8

android-2.2_r02-windows.zip

android-2.2_r02-macosx.zip

tools
tools_r05-windows.zip
tools_r05-linux.zip
tools_r05-macosx.zip

usb_d
usb_driver_r03-windows.zip

android使用ZipInputStream解压缩zip压缩文件

public class unzip extends Activity {
  /** Called when the activity is first created. */
  static final int BUFFER = 2048;
  TextView textView;
  @Override
  public void onCreate(Bundle savedInstanceState) {
    textView = new TextView(this);
    super.onCreate(savedInstanceState);
    textView.setText(“Main Activity”);
    extractZipfile();
    setContentView(textView);
  }
  private void extractZipfile() {
    String extractDir = getApplicationContext().getFilesDir()
            .getAbsolutePath()
            + “/unzip/”;
    try {
      BufferedOutputStream dest = null;
      ZipInputStream zis = new ZipInputStream(getResources()
              .openRawResource(R.raw.book));
      ZipEntry entry;
      while ((entry = zis.getNextEntry()) != null) {
        File file = new File(extractDir + entry.getName());
        if (file.exists()) {
          textView.append(“n” + file.getAbsolutePath() + “texists”);
          continue;
        }
        if (entry.isDirectory()) {
          if (!file.exists())
            file.mkdirs();
          textView.append(“nCreate directory: “
                  + file.getAbsolutePath());
          continue;
        }
        textView.append(“nExtracting:” + entry);
        int count;
        byte data[] = new byte[BUFFER];
        textView.append(” to ” + file.getAbsolutePath());
        FileOutputStream fos = new FileOutputStream(file);
        dest = new BufferedOutputStream(fos, BUFFER);
        while ((count = zis.read(data, 0, BUFFER)) != -1) {
          dest.write(data, 0, count);
        }
        dest.flush();
        dest.close();
      }
      zis.close();
    } catch (Exception e) {
        // TODO: handle exception
      e.printStackTrace();
    }
  }
}

解决Android屏幕方向变化的问题

作为一个Android开发新手,当我们在开发的时候面对一个大问题

“处理屏幕方向变化“

这个问题的原因是什么?

那么它会导致许多问题如下

   1。只要我们改变方向,它就会创建一个新的Activity
   2。如果在播放音频文件,这将重新载入两次文件,这将同时播放两个同样的歌
   3。导致内存管理问题。
   4。如果你有一个20字段的表单,填写了15个字段,就会丢失15个字段里的内容

那么如何解决这个问题。谷歌在manifest.xml一行代码解决问题

添加这行代码到Activity属性来解决这个问题。
android:configChanges=”orientation”

这样也行
<activityandroid:label=”@string/app_name”android:configChanges=”orientation”

android:name=”.com.androidpeople”>

现在你是完全从这个方向变化问题的自由