android icon多个入口、widget、DeskShortCut的创建

首先说明一下,这篇文章包含了几个小列子,算是整合了,有些是从网上找到的相关资源。

第一个例子是应用具有多个icon程序入口:及在launcher中显示多个icon图标,此好处是方便用户选择其所需要的模块,比如:拨号键和通讯录,google地图和google纵横。

        需要修改的地方有两处:

        ①AndroidManifest.xml处添加一个activity属性

<activity
            android:name=".TestIconWidgetActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".TestIcon2Acvtivity"
            android:icon="@drawable/ic_power"
            android:label="@string/app_name_1"
            android:launchMode="singleInstance" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

           此处添加了第二个activity,需要注意的是android:launchMode="singleInstance",此模式的意思请看本人转载的博客Android Activity的四种LaunchMode!!!

          ②添加一个activity类

public class TestIcon2Acvtivity extends Activity{
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main_2);
	}
}

         此时安装应用,在launcher功能列表中出现两个icon入口,截图如下:

       

第二个例子widget的开发,widget属性的配置,以及如何给应用添加多个widget

         ①AndroidManifest.xml中添加相应配置,内容如下:

<!-- 添加一个4*3的widget -->
        <receiver
            android:name="com.pb09java.widget.MyWidgetProvider3"
            android:label="全部 4 x 3" >
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/my_widget3" />
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
        </receiver>
        <!-- 添加一个4*2的widget -->
        <receiver
            android:name="com.pb09java.widget.MyWidgetProvider2"
            android:label="全部 4 x 2" >
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/my_widget2"/>
            <intent-filter>
                <action android:name="com.action.widget.click"/>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
            </intent-filter>
        </receiver>
        <!-- 添加一个4*1的widget -->
        <receiver
            android:name="com.pb09java.widget.MyWidgetProvider1"
            android:label="全部4 x 1" >
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/my_widget1" />
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
        </receiver>
        <!-- widget中跳转前设置activity -->
        <activity android:name="com.pb09java.widget.MyNoteConf2"
            android:icon="@drawable/ic_launcher" android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />  
            </intent-filter>
        </activity>

            以上代码包含三个widget的文件布局,android:resource="@xml/my_widget2"

            包含三个AppWidgetProvider类,MyWidgetProvider2继承AppWidgetProvider,此类里面做widget的刷新和逻辑的处理

            包含一个属性配置类,此类用于启动widget时跳转到activity进行配置,配置完成后跳转到widget,下面都会有介绍

         ②/xml/my_widget2.xml       

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"  
    android:minWidth="@dimen/widget2_width"  
    android:minHeight="@dimen/widget2_height"  
    android:updatePeriodMillis="1000"  
    android:configure="com.pb09java.widget.MyNoteConf2"
    android:initialLayout="@layout/widget2"
/>
<!-- 最小尺寸 = (单元格数*74)-2 -->
<!-- android:updatePeriodMillis 1.5版本后无用-->

       上面包含五个属性分别作出解释: minwidth为最小宽度,minHeight为最小高度,由于此widget是4*2的宽高,所以设置为294dip和142dip

        updatePeriodMillis属性本是widget刷新周期,但是无用,所以需要自定义Timer类刷新

       configure属性配置,及上文提到的启动widget时跳转的activity类,在manifest中已经配置
       /values/dimens.xml此文件为配置widget的宽高

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <!-- add 4*1 widget -->
    <dimen name="widget1_width">294dip</dimen>
    <dimen name="widget1_height">72dip</dimen>
   <!-- add 4*2 widget -->
    <dimen name="widget2_width">294dip</dimen>
    <dimen name="widget2_height">142dip</dimen>
    <!-- add 4*3 widget -->
    <dimen name="widget3_width">294dip</dimen>
    <dimen name="widget3_height">220dip</dimen>
</resources>

         ③MyNoteConf2.java代码如下:

public class MyNoteConf2 extends Activity {
	int mAppWidgetId;
	private ProgressDialog dialog;
	private Button ok;
	private Button cancel;
	private EditText userName;
	private EditText passWord;
	final public static int progressDialogId = 119;
	final public static int NotId = 1973;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.widgetconf2);
		
		ok = (Button) findViewById(R.id.ok);
		cancel = (Button) findViewById(R.id.cancel);
		userName = (EditText)findViewById(R.id.edit_name);
		passWord = (EditText)findViewById(R.id.edit_password);
		ok.setOnClickListener(okListener);
		cancel.setOnClickListener(cancelListener);
		
		// Find the widget id from the intent.
		//添加如下语句,其意图在于保存mAppWidgetId,传给AppWidgetProvider
		Intent intent = getIntent();
		Bundle extras = intent.getExtras();
		if (extras != null) {
			mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,
					AppWidgetManager.INVALID_APPWIDGET_ID);
		}

		// If they gave us an intent without the widget id, just bail.
		if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
			finish();
		}
	}
	@Override
	protected Dialog onCreateDialog(int id)
	{
		switch (id){
		case progressDialogId:
			dialog = new ProgressDialog(this);
			dialog.setCancelable(true);
			dialog.setTitle("加载页面中....");
			return dialog;
		}
		return super.onCreateDialog(id);
	}
	
	OnClickListener okListener = new OnClickListener() {
		@Override
		public void onClick(View v) {
			showDialog(progressDialogId);
			final Context context = MyNoteConf2.this;
			new Thread(){
				public void run() {
					try {
						saveTitlePref();
						// 取得AppWidgetManager实例
						AppWidgetManager appWidgetManager = AppWidgetManager
								.getInstance(context);
						// 更新AppWidget
						MyWidgetProvider2.updateAppWidget(context, appWidgetManager,
								mAppWidgetId, MyNoteConf2.this.getUserName(),MyNoteConf2.this.getPassWord());
						//此处休眠1秒代替其他耗时间的操作,比如网络的用户验证
						Thread.sleep(1000);
						
						//通过返回,Launcher中的onActivityResult方法通过传入的intent调用widget
						Intent resultValue = new Intent();
						resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
								mAppWidgetId);
						setResult(RESULT_OK, resultValue);
						
						dialog.dismiss();	
						finish();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				};
			}.start();
		}
	};
	OnClickListener cancelListener = new OnClickListener() {
		@Override
		public void onClick(View v) {
			finish();
		}
	};
	
	void saveTitlePref(){
		SharedPreferences localSharedPreferences = getSharedPreferences(
				"WIDGET_DATA", Context.MODE_PRIVATE);
		Editor localEditor = localSharedPreferences.edit();
		//添加用户名
		if(userName != null && userName.getText().toString().length()>0){
			localEditor.putString("USER_NAME", userName.getText().toString()).commit();
		}else{
			localEditor.putString("USER_NAME", "guest").commit();
		}
		//添加密码
		if(passWord != null && passWord.getText().toString().length()>0){
			localEditor.putString("PASSWORD", passWord.getText().toString()).commit();
		}else{
			localEditor.putString("PASSWORD", "guest").commit();
		}
	}
	public String getUserName() {
		return userName.getText().toString();
	}
	public String getPassWord() {
		return passWord.getText().toString();
	}
}

           此activity的布局文件/layout/widgetconf2.xml如下:

<?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" >
    <!-- 进入widget时的配置activity类的布局文件 -->
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/widget_conf" />
    <EditText android:id="@+id/edit_name"
            android:layout_width="fill_parent"
	        android:layout_height="wrap_content"
	        android:hint="@string/input_name"/>
     <EditText android:id="@+id/edit_password"
       		 android:layout_width="fill_parent"
     		 android:layout_height="wrap_content"
     		 android:hint="@string/input_passwd"/>
    <RelativeLayout android:orientation="horizontal"
        android:layout_width="fill_parent"
    	android:layout_height="fill_parent">
        <Button android:id="@+id/ok"
		    android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:text="@string/ok"/>
		<Button android:id="@+id/cancel" 
		    android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:layout_toRightOf="@+id/ok"
	        android:text="@string/cancel"/>
    </RelativeLayout>
</LinearLayout>

            包含两个编辑框,填写用户名和密码,确认和取消button。
           ④widget的显示ui配置文件/layout/widget2.xml代码如下:

<?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" 
    android:background="@drawable/appwidget_bg">
    
    <TextView android:id="@+id/widgetText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <TextView android:id="@+id/userName"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <TextView android:id="@+id/password"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <TextView android:id="@+id/olympicGames"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
</LinearLayout>
             ⑤MyWidgetProvider2.java代码如下:
public class MyWidgetProvider2 extends AppWidgetProvider {
	private static final String CLICK_NAME_ACTION = "com.action.widget.click";
	private static RemoteViews rv;
	
	private String userName, password;
	//为接收广播时调用更新UI
	@Override
	public void onReceive(Context context, Intent intent) {
		super.onReceive(context, intent);
		if (rv == null) {
			rv = new RemoteViews(context.getPackageName(), R.layout.widget2);
		}
		if (intent.getAction().equals(CLICK_NAME_ACTION)) {
			if (Uitil.isChange) {
				rv.setTextViewText(R.id.widgetText, context.getResources()
						.getString(R.string.load));

			} else {
				rv.setTextViewText(R.id.widgetText, context.getResources()
						.getString(R.string.change));

			}
			Toast mToast = Toast.makeText(context, Boolean.toString(Uitil.isChange),
					Toast.LENGTH_SHORT);
			//此处设置显示的位置
			mToast.setGravity(Gravity.TOP, 0, 10);
			//让其显示
			mToast.show();
			Uitil.isChange = !Uitil.isChange;

		}
		AppWidgetManager appWidgetManger = AppWidgetManager
				.getInstance(context);
		int[] appIds = appWidgetManger.getAppWidgetIds(new ComponentName(
				context, MyWidgetProvider2.class));
		appWidgetManger.updateAppWidget(appIds, rv);
	}
	
	//删除组件时调用
	@Override
	public void onDeleted(Context context, int[] appWidgetIds) {
		super.onDeleted(context, appWidgetIds);
	}

	//当第一个组件删除时调用
	@Override
	public void onDisabled(Context context) {
		super.onDisabled(context);
	}

	//当第一个组件创建时调用
	@Override
	public void onEnabled(Context context) {
		super.onEnabled(context);
	}

	/**
	 * 周期更新时调用
	 * android:updatePeriodMillis 1.5版本后无用
	 * 故需要周期刷新widget得自动通过Timer更新
	 */
	public void onUpdate(Context context, AppWidgetManager appWidgetManager,
			int[] appWidgetIds) {
		if(userName == null && password == null){
			SharedPreferences localSharedPreferences = context.getSharedPreferences(
					"WIDGET_DATA", Context.MODE_PRIVATE);
			this.userName = localSharedPreferences.getString("USER_NAME", "guest");
			this.password = localSharedPreferences.getString("PASSWORD", "guest");
		}
		final int N = appWidgetIds.length;
		for (int i = 0; i < N; i++) {
			int appWidgetId = appWidgetIds[i];
			updateAppWidget(context, appWidgetManager, appWidgetId, userName, password);
		}
//		Timer timer = new Timer();  
//		timer.scheduleAtFixedRate(new MyTime(context,appWidgetManager), 1, 1000);  
	}
	
	public static void updateAppWidget(Context context,
		AppWidgetManager appWidgeManger, int appWidgetId, String userName, String password) {
		//构建RemoteViews对象来对桌面部件进行更新
		rv = new RemoteViews(context.getPackageName(), R.layout.widget2);
		//更新文本内容,指定布局的组件
		rv.setTextViewText(R.id.userName, userName);
		rv.setTextViewText(R.id.password, password);
		//为RemoteViews添加点击事件监听
		Intent intentClick = new Intent(CLICK_NAME_ACTION);
		PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
				intentClick, 0);
		rv.setOnClickPendingIntent(R.id.widgetText, pendingIntent);
		//将RemoteViews的更新传入AppWidget进行更新
		appWidgeManger.updateAppWidget(appWidgetId, rv);
	}
}
 

        此时代码修改完毕,看实际效果图:

 

              第三个例子,安装应用后提示是否创建DeskShortCut:

             ①Androidmanifest.xml文件添加权限

<!-- 添加快捷方式的权限 -->
 	<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>

            ②TestIconWidgetActivity.java源码如下:

public class TestIconWidgetActivity extends Activity {
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}
	@Override
	protected void onResume() {
		super.onResume();
		
		SharedPreferences preferences = getSharedPreferences("first",
				Context.MODE_PRIVATE);
		boolean isFirst = preferences.getBoolean("isfrist", true);
		if (isFirst) {
			HandlerThread mHandlerThread = new HandlerThread("handler_thread");
			mHandlerThread.start();
			
			MyHandler myHandler = new MyHandler(mHandlerThread.getLooper());
			myHandler.post(new Runnable() {
				@Override
				public void run() {
					Dialog mDialog =  new AlertDialog.Builder(TestIconWidgetActivity.this)
					.setTitle("是否添加桌面快捷键")
					.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							createDeskShortCut();
							dialog.dismiss();
						}
					})
					.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							dialog.dismiss();
						}
					})
					.setOnKeyListener(new DialogInterface.OnKeyListener() {
						public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
							if(event.getKeyCode() == KeyEvent.KEYCODE_SEARCH){
								return true;
							}
							return false;
						}
					})
					.setCancelable(false)
					.create();
					mDialog.show();
				}
			});
		}
		SharedPreferences.Editor editor = preferences.edit();
		editor.putBoolean("isfrist", false);
		editor.commit();
	}
	
	class MyHandler extends Handler{
		public MyHandler(){
			
		}
		public MyHandler(Looper looper){
			super(looper);
		}
		@Override
		public void handleMessage(Message msg) {
			System.out.println("Handler--->" + Thread.currentThread().getId());
			System.out.println("handlerMessage");
		}
	}
	/**
	 * 创建快捷方式
	 */
	public void createDeskShortCut() {
		Log.i("coder", "------createShortCut--------");
		// 创建快捷方式的Intent
		Intent shortcutIntent = new Intent(
				"com.android.launcher.action.INSTALL_SHORTCUT");
		// 不允许重复创建
		shortcutIntent.putExtra("duplicate", false);
		// 需要现实的名称
		shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME,
				getString(R.string.app_name));

		// 快捷图片
		Parcelable icon = Intent.ShortcutIconResource.fromContext(
				getApplicationContext(), R.drawable.ic_pressure);

		shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon);

		Intent intent = new Intent(getApplicationContext(),
				TestIconWidgetActivity.class);
		// 下面两个属性是为了当应用程序卸载时桌面 上的快捷方式会删除
		intent.setAction("android.intent.action.MAIN");
		intent.addCategory("android.intent.category.LAUNCHER");
		// 点击快捷图片,运行的程序主入口
		shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, intent);
		// 发送广播。
		sendBroadcast(shortcutIntent);
	}
}

            在onResume方法中开启handler完成判断是否为一次开启,并询问第一次开启是否创建桌面快捷方式

           效果图如下:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值