转自: http://www.52rd.com/Blog/Detail_RD.Blog_jimbo_lee_30433.html
http://www.52rd.com/Blog/Detail_RD.Blog_jimbo_lee_30865.html
编译代码步骤:
一.无源代码目录时
1.登录编译服务器
进入命令行执行 ssh release@192.168.1.30
2.从GIT服务器上下载代码
1). curl http://192.168.1.29/repo/repo >repo //下载repo脚本
2). chmod +x repo //修改repo的权限
3). ./repo init -u http://192.168.1.29/repo/hct-mtk/6513-v1.37/manifests.git/ //初始化repo
4). ./repo sync //同步MASTER分支到本地
3.开启release分支
./repo start release --all
4. 下载release分支内容到本地
./repo download `./repo list | awk -F: '{print $1}'` -m
5. 拷贝项目分支到根目录
./distribute.sh -p ****
6. 修改版本号码
vi mediatek/config/hct13_gb/ProjectConfig.mk
修改MTK_BUILD_VERNO = P90.r1
7. 开始编译
/distribute.sh -mtk new
8.编译完成打包
./distribute.sh -b
9.拷贝编译好的包到制定目录
mv *** ../Public/distribute
二.存在有源代码目录时
1、./distri.sbuteh -mtk clean 先清空编译过的中间代码
2、./repo forall -c git clean -d -f 清空未受管控代码
3、./repo forall -c git checkout -f 同步本地代码跟服务器完全相同(去除本地所有修改)
4、./repo status 查看本地代码
5、./repo list | sed 's/:.*//' | xargs ./repo download -m 列出所有受管控的代码库并merge下载
6、 ./repo start release dists/ 设置到release目录
./repo download --br develop -m dists/ 合入到realease 分支
7、./distribute.sh -p projectname 把项目相关的目录覆盖到根目录下
8、vi mediatek/config/hct13_gb/ProjectConfig.mk 编辑版本号
9、./distribute.sh -mtk -o=TARGET_BUILD_VARIANT=user new 编译版本
1.壁纸
/mediatek/source/frameworks/banyan/res/res/drawable/lockscreen_default_wallpaper.png 320X480 可以自动拉伸,slide lock screen 的默认壁纸
/frameworks/base/core/res/res/drawable/default_wallpaper.jpg 640X480 ,默认墙纸
/packages/apps/Launcher2/res/drawable-hdpi/wallpapers.xml 墙纸列表
/frameworks/base/core/res/res/values/config.xml <string name="default_wallpaper_component">@null</string> 修改为:<string name="default_wallpaper_component">动态墙纸包名/.动态墙纸类名</string> , 动态墙纸
/packages/apps/Launcher2/res/xml/default_workspace.xml 预置桌面项目
/frameworks/base/media/java/android/media/AudioManager.java DEFAULT_STREAM_VOLUME 默认的音量和来电铃声
修改 build\target\product\下的 core.mk 文件,添加 ro.config.ringtone=对应铃声文件名 即可
/frameworks/base/data/sounds/Android.mk 铃声列表
/frameworks/base/core/res/assets/images/android-logo-mask.png 开机logo
这个动画是由两个图片通过 openGL 叠加出来的,文件分别为:
/frameworks/base/core/res/assets/images/android-logo-mask.png
Android 默认的前景图片,文字部分镂空,大小 256×64
/frameworks/base/core/res/assets/images/android-logo-shine.png
Android 默认的背景图片,有动感效果,大小 512×64
只要把 android-logo-mask.png 替换成想要的 png 图片就可以了。
实现开机铃声:
可以在 BootAnimation.cpp 文件的 BootAnimation::android() 中实现
在这个函数的最开始部分加入
sp<MediaPlayer> mp = new MediaPlayer();
mp->setDataSource("/system/media/audio/notifications/TaDa.ogg", NULL);
mp->prepare();
mp->start();
这里的音乐文件路径可以自己更改(注意这时候 sdcard 还没有挂上来,不要用 sdcard 中的
音乐文件)。
然后在这个函数的结束再加上
mp->stop();
mp->disconnect();
mp->setListener(NULL);
mp = NULL;
更换开机铃声:
先将要设置为铃声的音乐文件更名为 bootanimation.mp3,注意需要为 mp3 文件方能生效。
将该文件放入工程的资源目录下 frameworks\base\data\sounds\newwavelabs,修改
Android.mk 文件,将该文件打到 data\local\路径下,添加如下语句:
$(LOCAL_PATH)/newwavelabs/bootanimation.mp3:data/local/bootanimation.mp3
再次 build 工程即可
恢复出厂设置过后,开机动画和开机铃声为设置后的,非 Google 默认的开机动画和铃声
将该文件放入工程的资源目录下,如 frameworks\base\data\sounds\newwavelabs,修
改 Android.mk 文件,将该文件打到 system\media\路径下,添加如下语句:
MediaTek Confidential
© 2007 MediaTek Inc.
The information contained in this document can be modified without notice
Page: 20 of 75
FAQ
$(LOCAL_PATH)/newwavelabs/bootanimation.mp3:system/media/bootanimation.mp3
再次 build 工程即可。
bootanimation.zip 的制作方法举例如下:
分别创建名为“part0”和“part1”的文件夹以及一个名为“desc.txt”文件。“part0”
中存储动画的第一阶段的资源图片,“part1”存储第二阶段的资源图片,注意图片为
png 格式。
播放控制由“desc.txt”指定,内容如下:
320 480 30
p 1 0 part0
p 0 0 part1
各参数功能如下:
320 480 30
宽 高 帧率(每秒播放多少帧图片)
p 1 0 part0
标志符 循环次数 阶段切换间隔时间 对应目录名
p 0 0 part1
标志符 循环次数 阶段切换间隔时间 对应目录名
最后,将这三个组件通过存储压缩的方式压缩为 bootanimation.zip 文件即制作完成。
预制开机动画的过程如下:
将 制 作 完 成 的 bootanimation.zip 文 件 放 在 工 程 的 资 源 目 录 下 , 如
frameworks\base\data\sounds 目录下,修改 Android.mk 文件,通过以下语句将该压缩
包打到 system\medial\路径下:
$(LOCAL_PATH)/bootanimation.zip:system/media/bootanimation.zip
再次 build 工程即可。
举例:
480 320 15
p 2 30 folder0 //将folder0里的图片,播放2遍,播放完一遍后停顿30帧,因为我们之前设置了帧率是15帧每秒,那么这里就等于停顿2秒。p 0 0 folder1 //将folder1里的图片无限循环播放,每次播放不停顿
如何获取当前的情景模式 和设置不同的情景模式?
首 先 通 过 getSystemService(Context.AUDIO_SERVICE) 获 取 AudioManager 的 实 例 audioManager 。然后调用set/get方法
铃声和震动:
audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
audioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,
AudioManager.VIBRATE_SETTING_ON);
audioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,
AudioManager.VIBRATE_SETTING_ON);
铃声:
audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
audioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,
AudioManager.VIBRATE_SETTING_OFF);
audioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,
AudioManager.VIBRATE_SETTING_OFF);
Cen
震动:
audioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
audioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,
AudioManager.VIBRATE_SETTING_ON);
audioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,
AudioManager.VIBRATE_SETTING_ON);
静音:
audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
audioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,
AudioManager.VIBRATE_SETTING_OFF);
audioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,
AudioManager.VIBRATE_SETTING_OFF);
在一个Activity去除Statusbar和Titlebar
修改对应的 Activity,添加以下代码:
final Window win = getWindow();
win.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);//remove statusbar
requestWindowFeature(Window.FEATURE_NO_TITLE);
requestWindowFeature(Window.FEATURE_PROGRESS);//remove titlebar
注意:必须添加在 setContentView()方法之前,否则将提示错误。
如何拦截来电,即在电话 ring 之前就有机会检查来电号码?
packages\apps\Phone\src\com\android\phone\CallNotifier.java onNewRingingConnection
根据需要从Connection c = (Connection) r.result; 中来电连接中分析来电数据,从而判定是否要拦截。
何拦截短信? 即新短信来时,能否在提示给用户之前检查短信来源和内容。
可以在 SmsReceiverService.java 的 insertMessage 方法里拦截。短信的来源和内容都可以通过 class SmsMessage 提供的方法获取。
如可以通过 getOriginatingAddress 方法获取,内容则可以通过 getMessageBody 方法获取。如果满足拦截的条件,就不做 storeMessage 的动作。
修改默认时间:
\alps\mtk\src\custom\[project]\preloader\custom\custom\inc\cust_rtc.h
\alps\mtk\src\custom\[project]\kernel\rtc\rtc\rtc-mt6516.h
#define RTC_DEFAULT_YEA
#define RTC_DEFAULT_MTH
#define RTC_DEFAULT_DOM
1. 修改文件 alps\frameworks\base\packages\SettingsProvider\res\values\defaults.xml
增加代码<string name="time_12_24" translatable="false">24</string>
红色标记表示 24 小时制,也可以改为 12(12 小时制)
2. 修改文件
alps\frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\Databas
eHelper.java
找到函数 loadSystemSettings (),在函数中增加以下语句:
loadStringSetting(stmt, Settings.System.TIME_12_24, R.string.time_12_24);
修改蓝牙设备的默认名称
修改 frameworks\base\core\jni\Android_bluetooth_common.h
将 BTMTK_ANDROID_DEFAULT_LOCAL_NAME 值改掉,注意此处有引号。
#define BTMTK_ANDROID_DEFAULT_LOCAL_NAME "ANDROID BT"
Call requires API level 5 (current min is 1)
解决措施:
<use-sdk android:minSdkVersion="10"
android:targetSdkVersion="10" >
</use-sdk>
1、ImageView使用:
(1)、加载资源中的图片:
image1.setImageResource(R.drawable.f2);
(2)、加载本地图片:
ImageView image1 = (ImageView) findViewById(R.id.iv1); //获得ImageView对象
Bitmap bitmap = getLoacalBitmap("/sdcard/tubiao.jpg"); //从本地取图片(在cdcard中获取) //
image1 .setImageBitmap(bitmap); //设置Bitmap
public static Bitmap getLoacalBitmap(String url) {
try {
FileInputStream fis = new FileInputStream(url);
return BitmapFactory.decodeStream(fis); ///把流转化为Bitmap图片
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
}
扩展学习
BitmapFactory(android.graphics.BitmapFactory)是Android API提供的对象,可以将图片文件转换成Bitmap(android.graphics.Bitmap)对象,范例中使用的decodeFile()可以将手机文件系统中的图片文件转换成Bitmap对象。另外,BitmapFactory也提供了其他的方法,如decodeResource()可以将 /res/drawable/内预先存入的图片文件转换成Bitmap对象,decodeStream()方法则可将InputStream转换成Bitmap对象。
(3)、加载网络图片:
3、获取网络上的图片
ImageView image1 = (ImageView) findViewById(R.id.iv1);
Bitmap bitmap =getHttpBitmap("http://images.missyuan.com/attachments/day_071123/20071123_b2bfefe1ec56e2df6582vCGIZG81gbyM.png"); //从网上取图片
image1 .setImageBitmap(bitmap); //设置Bitmap
从服务器取图片
public static Bitmap getHttpBitmap(String url) {
URL myFileUrl = null;
Bitmap bitmap = null;
try {
myFileUrl = new URL(url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
HttpURLConnection conn = (HttpURLConnection) myFileUrl.openConnection();
conn.setConnectTimeout(0);
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
bitmap = BitmapFactory.decodeStream(is);
is.close();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
注意:由于需要使用网络,所以 AndroidManfest.xml 文件需要添加使用网络权限!!!
<uses-permission android:name="android.permission.INTERNET" />
这也是我为什么一直错,而且一直找不到原因,它就是不显示图片,什么错误都没有,坑爹啊!!
并可用Activity中的getText(R.string.hello)直接转成字符串
调用拨号界面拨打电话:
Uri telUri = Uri.parse("tel:1008611");
Intent intent= new Intent(Intent.ACTION_DIAL, telUri);
//intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
<uses-permission android:name="android.permission.CALL_PHONE"></uses-permission> 拨号权限
android 如何实现跳转到发短信界面,并指定短信内容:
Uri smsToUri = Uri.parse("smsto://10086");
Intent mIntent = new Intent( android.content.Intent.ACTION_SENDTO, smsToUri );
mIntent.putExtra("sms_body", "this is content");
startActivity( mIntent );
启动activity:
//Intent launchAppIntent = new Intent(context, WidgetSetting.class);
Intent launchAppIntent = new Intent();
launchAppIntent.setClass(context, WidgetSetting.class); 从context activity 跳到 WidgetSetting activity
launchAppIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 不同进程间跳转
context.startActivity(launchAppIntent);
android:process=":lee.study.widget.main" 在新进程中启动activity
widget中的按键处理:
在onUpdate函数中添加代码
Intent intent=new Intent(ACT_SETTING);
PendingIntent myPendingIntent= PendingIntent.getBroadcast(context, 0, intent, 0);
// PendingIntent myPendingIntent= PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);// 如果Intent不带数据,则最后一个参数设为0
remoteViews.setOnClickPendingIntent(R.id.button_setting, myPendingIntent);
ComponentName cmp = new ComponentName(context, WidgetDemo.class);
AppWidgetManager myAppWidgetManager = AppWidgetManager.getInstance(context);
myAppWidgetManager.updateAppWidget(cmp, remoteViews);
在onReceive函数中添加处理的代码:
if(intent.getAction().equals(ACT_SETTING)) {
// 收到并处理自定义的消息
// Intent launchAppIntent = new Intent(context, WidgetSetting.class);
Intent launchAppIntent = new Intent();
launchAppIntent.setClass(context, WidgetSetting.class);
launchAppIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(launchAppIntent);
AppWidgetManager appWidgetManger = AppWidgetManager.getInstance(context);
int[] appIds = appWidgetManger.getAppWidgetIds(new ComponentName(context, WidgetDemo.class));
appWidgetManger.updateAppWidget(appIds, remoteViews);
}else{
super.onReceive(context, intent);
}
在AndroidManifest.xml要增加
<receiver android:name=".WidgetDemo" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="lee.study.widget.SETTING"></action>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_provider" />
</receiver>
其中 lee.study.widget.SETTING 就是 代码中ACT_SETTING的字串
在程序中访问SDCard,你需要申请访问SDCard的权限.
在AndroidManifest.xml中加入访问SDCard的权限如下:
<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
Environment.getExternalStorageState()方法用于获取SDCard的状态,如果手机装有SDCard,并且可以进行读写,那么方法返回的状态等于Environment.MEDIA_MOUNTED.
如何将一个Activity设置成窗口的样式:
在AndroidManifest.xml 中定义Activity的地方一句话android:theme="@android:style/Theme.Dialog" 或 android:theme="@android:style/Theme.Translucent"就变成半透明的
数据存储:
1.文件、
在Android中通常使用File存储方式是用 Context.openFileOutput(String fileName, int mode)和Context.openFileInput(String fileName)。
Context.openFileOutput(String fileName, int mode)生成的文件自动存储在/data/data/Package Name/files目录下,其全路径是/data/data/Package Name/files/fileName 。注意下,这里的参数fileName不可以包含路径分割符(如"/")。
通常来说,这种方式生成的文件只能在这个apk内访问。但这个结论是指使用Context.openFileInput(String fileName)的方式。使用这种方式,每个apk只可以访问自己的/data/data/Package Name/files目录下的文件,原因很简单,参数fileName中不可以包含路径分割符,Android会自动在/data/data /Package Name/files目录下寻找文件名为fileName的文件。
String fn = “moandroid.log”;
FileInputStream fis = openFileInput(fn);
FileOutputStream fos = openFileOutput(fn,Context.MODE_PRIVATE);
除此之外,Android还提供了其他函数来操作文件,详细说明请阅读Android SDK。
2、SharedcPreferences、
首先说明SharedPreferences存储方式,它是 Android提供的用来存储一些简单配置信息的一种机制,例如:登录用户的用户名与密码。其采用了Map数据结构来存储数据,以键值的方式存储,可以简单的读取与写入,具体实例如下:
void ReadSharedPreferences(){
String strName,strPassword;
SharedPreferences user = getSharedPreferences(“user_info”,0);
strName = user.getString(“NAME”,””);
strPassword = user getString(“PASSWORD”,””);
}
void WriteSharedPreferences(String strName,String strPassword){
SharedPreferences user = getSharedPreferences(“user_info”,0);
uer.edit();
user.putString(“NAME”, strName);
user.putString(“PASSWORD” ,strPassword);
user.commit();
}
3、ContentProvider:
如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
Uri uri = Uri.parse("content://com.changcheng.provider.contactprovider/contact")
ContentResolver:当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用 ContentResolver 类来完成,要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法。 ContentResolver使用insert、delete、update、query方法,来操作数据。
4、SQLite数据库存储数据:
5、网络存储:
service使用:
第一步:继承Service类
public class SMSService extends Service {
}
第二步:在AndroidManifest.xml文件中的<application>节点里对服务进行配置:
<service android:name=".SMSService" />
服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。这两个方法都可以启动Service,但是它们的使用场合有所不同。使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。
如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。
如果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法。
服务常用生命周期回调方法如下:
onCreate() 该方法在服务被创建时调用,该方法只会被调用一次,无论调用多少次startService()或bindService()方法,服务也只被创建一次。
onDestroy()该方法在服务被终止时调用。
与采用Context.startService()方法启动服务有关的生命周期方法
onStart() 只有采用Context.startService()方法启动服务时才会回调该方法。该方法在服务开始运行时被调用。多次调用startService()方法尽管不会多次创建服务,但onStart() 方法会被多次调用。
与采用Context.bindService()方法启动服务有关的生命周期方法
onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。
onUnbind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务解除绑定时被调用
采用Context.startService()方法启动服务的代码如下:
public class HelloActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
......
Button button =(Button) this.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
Intent intent = new Intent(HelloActivity.this, SMSService.class);
startService(intent);
}});
}
}
采用Context. bindService()方法启动服务的代码如下:
public class HelloActivity extends Activity {
ServiceConnection conn = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
}
public void onServiceDisconnected(ComponentName name) {
}
};
@Override public void onCreate(Bundle savedInstanceState) {
Button button =(Button) this.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
Intent intent = new Intent(HelloActivity.this, SMSService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
//unbindService(conn);//解除绑定
}});
}
}
Activity生命周期:
横竖屏切换时候 activity 的生命周期
1. 不设置 Activity 的 android:configChanges 时 , 切屏会重新调用各个生命周期 , 切横屏时会执行一次 , 切竖屏时会执行两次 .
2. 设置 Activity 的 android:configChanges=”orientation” 时 , 切屏还是会重新调用各个生命周期 , 切横、竖屏时只会执行一次 .
3. 设置 Activity 的 android:configChanges=”orientation|keyboardHidden” 时 , 切屏不会重新调用各个生命周期 , 只会执行 onConfigurationChanged 方法 .
{
// 推荐的定时器的使用方法:
Timer timer2 = new Timer();
Handler handler = new Handler(){
public void handleMessage(Message msg){
switch (msg.what) {
case 1:
// 自己的操作
break;
default:
super.handleMessage(msg);
break;
}
}
};
TimerTask task = new TimerTask() {
@Override
public void run() {
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
};
timer.schedule(task, 1000);
}
// 本身的定时功能
private Handler handler = new Handler();
private Runnable myRunnable = new Runnable() {
@Override
public void run() {
handler.postDelayed(this, 1000);
//自己的定时处理
}
};
// 然后在其他地方调用 handler.post(myRunnable); 或 handler.postDelayed(myRunnable, delayMillis);
view的刷新函数:
View.postInvalidate();
View.postInvalidate(left, top, right, bottom);
View.postInvalidateDelayed(delayMilliseconds);
View.postInvalidateDelayed(delayMilliseconds, left, top, right, bottom);
推荐使用handler处理:
App widget 定时刷新操作:
public void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {
Timer timer = new Timer();
timer.scheduleAtFixedRate(new MyTime(context, appWidgetManager), 1, 2000);
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
private class MyTime extends TimerTask {
RemoteViews remoteViews;
AppWidgetManager appWidgetManager;
ComponentName thisWidget;
public MyTime(Context context, AppWidgetManager appWidgetManager) {
this.appWidgetManager = appWidgetManager;
remoteViews = new RemoteViews(context.getPackageName(), R.layout.main);
thisWidget = new ComponentName(context, WidgetDemo.class);
}
public void run() {
Date date = new Date();
Calendar calendar = new GregorianCalendar(2014, 06, 11);
// long days = (((calendar.getTimeInMillis() - date.getTime()) / 1000)) / 86400;
long seconds = (calendar.getTimeInMillis() - date.getTime()) / 1000;
// remoteViews.setTextViewText(R.id.wordcup, "距离南非世界杯还有" + days + "天");
remoteViews.setTextViewText(R.id.wordcup, "距离南非世界杯还有" + seconds+ "秒");
appWidgetManager.updateAppWidget(thisWidget, remoteViews);
}
}
//隐藏状态栏
Object service = getSystemService("statusbar");
Class<?> statusBarManager = Class.forName("android.app.StatusBarManager");
Method expand = statusBarManager.getMethod("disable", int.class);
expand.invoke(service, 0x00000000);
权限:
<uses-permission android:name="android.permission.STATUS_BAR"/>
<uses-permission android:name="android.permission.DISABLE_STATUS_BAR"/>
并使用系统签名
Sim卡联系人的增删改查:
TelephonyManager.getSimState() 取得sim卡状态
Uri: content://icc/adn/
操作跟其他的contenProvider一样 参考文件:/frameworks/base/telephony/java/com/android/internal/telephony/IccProvider.java
Android 权限:
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.CALL_PHONE" /> <!-- 拨号权限 -->
<uses-permission android:name="android.permission.CALL_PRIVILEGED" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
<uses-permission android:name="android.permission.ADD_SYSTEM_SERVICE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.REORDER_TASKS" />
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.STATUS_BAR" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.SET_TIME_ZONE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> TelephonyManager.getSimState() 取得sim卡状态
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.DEVICE_POWER" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
<uses-permission android:name="android.permission.BROADCAST_SMS"/>
<uses-permission android:name="android.permission.BROADCAST_WAP_PUSH"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SHUTDOWN" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.BACKUP" />
<uses-permission android:name="android.permission.USE_SIP" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.STOP_APP_SWITCHES" />
<uses-permission android:name="android.permission.SEND_SMS" />
把自己的程序导入到手机验证:
adb remount system/framework
adb push out/target/product/hct13_gb/system/framework/hctlockscreen.jar system/framework
查看相关的log:
adb logcat | grep "widget"
数据库调试:
adb devices
adb -s emulator-5554 shell
sqlite3 /data/data/lee.app.widget/databases/imageWidget.db3
INSERT INTO widget_info (widget_id, is_recycle, is_show_frame, time_interval, time_weight, widger_size, image1_path) VALUES (999, 0, 0, 50, 0, 0, 'image1_path');
select * from widget_info;
Android Widget中AppWidget按钮事件: 转:http://mobile.51cto.com/widget-289939.htm
Android Widget中appWidget按钮事件是本文要介绍的内容,主要是了解并学习Android Widget应用中appWidget事件,具体内容的实现来看本文详解。
在appWidget中,ImageButton和Button都是被支持的控件,其事件可分成三种类型:
一、开启Activity
1、首先先定义个开启Activity的intent
eg: Intent fullIntent=new Intent(this ,FullScreen.class);
若要传递数据,则使用intent.putExtra()方法
eg: fullIntent.putExtra("isCircle", isCircle);
2、用intent实例化一个PendingIntent,调用pendingIntent的getActicity方法来启动另一个Activity
(1)若该Intent带有数据,则需要将最后一个参数的值设为:FLAG_CANCEL_CURRENT
eg: PendingIntent Pfullintent= PendingIntent.getActivity(this, 0, fullIntent, PendingIntent.FLAG_CANCEL_CURRENT);
(2)若该Intent不带数据,则最后一个参数设为0
eg: PendingIntent Pfullintent= PendingIntent.getActivity(this, 0, fullIntent, 0);
3、实例化RemoteView,其对应相应的Widget布局
eg: RemoteViews views= new RemoteViews(getPackageName(), R.layout.widget);
4、给RemoteView上的Button或ImageButton设置按钮事件
eg: views.setOnClickPendingIntent(R.id.IBfullscreen, Pfullintent);
5、更新AppWidget界面
(1)如果是在onUpdate()方法内更新AppWidget界面
eg: appWidgetManager.updateAppWidget(appWidgetIds, ActivityView);
(2)如果是在onUpdate()方法外(一般为Service内)更新AppWidget界面,则需要定义几个变量
eg: public RemoteViews views; //RemoteView对象
public ComponentName thisWidget; //组件名
public AppWidgetManager manager; // AppWidget管理器
thisWidget = new ComponentName(this, PictureAppWidgetProvider.class);
manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(thisWidget, views);
二、开启Service
1、定义一个intent来开启Service
eg: Intent startServiceInten=new Intent("zyf.temp.Service.START");
注:参数为开启Service的动作
2、用Intent实例化一个PendingIntent,利用PendingIntent的getService方法来启动一个服务
eg: PendingIntent Pintent= PendingIntent.getService(context, 0, startServiceInten, 0);
3、实例化RemoteView,其对应相应的Widget布局
eg: RemoteViews views= new RemoteViews(getPackageName(), R.layout.widget);
4、给RemoteView上的Button或ImageButton设置按钮事件
eg: views.setOnClickPendingIntent(R.id.IBfullscreen, Pfullintent);
5、更新AppWidget界面
(1)如果是在onUpdate()方法内更新AppWidget界面
eg: appWidgetManager.updateAppWidget(appWidgetIds, ActivityView);
(2)如果是在onUpdate()方法外(一般为Service内)更新AppWidget界面,则需要定义几个变量
eg: public RemoteViews views; //RemoteView对象
- public ComponentName thisWidget; //组件名
- public AppWidgetManager manager; // AppWidget管理器
- thisWidget = new ComponentName(this, PictureAppWidgetProvider.class);
- manager = AppWidgetManager.getInstance(this);
- manager.updateAppWidget(thisWidget, views);
三、发送按钮Action
1、定义一个Intent来发送按钮Action
eg: Intent prevInten=new Intent("PREV");
2、用Intent实例化一个PendingIntent,利用PendingIntent的getBroadcast方法来发送广播
eg: PendingIntent Pprevintent= PendingIntent.getBroadcast(this, 0, prevInten, 0);
3、实例化RemoteView,其对应相应的Widget布局
eg: RemoteViews views= new RemoteViews(getPackageName(), R.layout.widget);
4、给RemoteView上的Button或ImageButton设置按钮事件
eg: views.setOnClickPendingIntent(R.id.IBprev, Pprevintent);
5、更新AppWidget界面
(1)如果是在onUpdate()方法内更新AppWidget界面
eg: appWidgetManager.updateAppWidget(appWidgetIds, ActivityView);
(2)如果是在onUpdate()方法外(一般为Service内)更新AppWidget界面,则需要定义几个变量
eg: public RemoteViews views; //RemoteView对象
public ComponentName thisWidget; //组件名
public AppWidgetManager manager; // AppWidget管理器
thisWidget = new ComponentName(this, PictureAppWidgetProvider.class);
manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(thisWidget, views);
6、接收该Action
1、在AppWidget自己的onReceive方法内接收
(1)在Action,要在Manifest.xml中加入Action
eg: <intent-filter>
- <action android:name="android.appwidget.action.APPWIDGET_UPDATE"> </action>
- <action android:name="PREV"></action>
- </intent-filter>
(2)在onReceive()方法内编写要实现的动作
- eg: if(intent.getAction().equals("PREV"))
- {
- //在这编写接收到该Action后要实现的动作
- }
2、在Service内接收
(1)注册一个BroadcastReceive,声明接收器
eg:
IntentFilter filter=new IntentFilter();
- filter.addAction("PREV");
- registerReceiver(doCommand, filter);
(2)在BroadcastReceive类的onReceive方法内编写要实现的动作
- eg: if(intent.getAction().equals("PREV"))
- {
- //在这编写接收到该Action后要实现的动作
- }
序列化Serializable总结
1、序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。
2、什么情况下需要序列化 a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候; b)当你想用套接字在网络上传送对象的时候; c)当你想通过RMI传输对象的时候; 3、当对一个对象实现序列化时,究竟发生了什么? 在没有序列化前,每个保存在堆(Heap)中的对象都有相应的状态(state),即实例变量(instance ariable)比如: java 代码 Foo myFoo = new Foo(); myFoo.setWidth(37); myFoo.setHeight(70); 当通过下面的代码序列化之后,MyFoo对象中的width和Height实例变量的值(37,70)都被保存到foo.ser文件中,这样以后又可以把它 从文件中读出来,重新在堆中创建原来的对象。当然保存时候不仅仅是保存对象的实例变量的值,JVM还要保存一些小量信息,比如类的类型等以便恢复原来的对 象。 java 代码 FileOutputStream fs = new FileOutputStream("foo.ser"); ObjectOutputStream os = new ObjectOutputStream(fs); os.writeObject(myFoo); 4、实现序列化(保存到一个文件)的步骤 a)Make a FileOutputStream java 代码 FileOutputStream fs = new FileOutputStream("foo.ser"); b)Make a ObjectOutputStream java 代码 ObjectOutputStream os = new ObjectOutputStream(fs); c)write the object java 代码 os.writeObject(myObject1); os.writeObject(myObject2); os.writeObject(myObject3); d) close the ObjectOutputStream java 代码 os.close(); 5、举例说明 java 代码 import java.io.*; public class Box implements Serializable { private int width; private int height; public void setWidth(int width){ this.width = width; } public void setHeight(int height){ this.height = height; } public static void main(String[] args){ Box myBox = new Box(); myBox.setWidth(50); myBox.setHeight(30); try{ FileOutputStream fs = new FileOutputStream("foo.ser"); ObjectOutputStream os = new ObjectOutputStream(fs); os.writeObject(myBox); os.close(); }catch(Exception ex){ ex.printStackTrace(); } } } 6、相关注意事项 a)序列化时,只对对象的状态进行保存,而不管对象的方法; b)当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口; c)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化; d)并非所有的对象都可以序列化,,至于为什么不可以,有很多原因了,比如: 1.安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行rmi传输 等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的。 2. 资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分 配,而且,也是没有必要这样实现。 平衡二叉树(解惑) 平衡二叉树定义(AVL):它或者是一颗空树,或者具有以下性质的二叉树:它的左子树和右子树的深度之差的绝对值不超过1,且它的左子树和右子树都是一颗平衡二叉树。 如何判断little-endian big-endian bool IsBig_Endian() //如果字节序为big-endian,返回true; //反之为 little-endian,返回false { unsigned short test = 0x1122; if(*( (unsigned char*) &test ) == 0x11) return TRUE; else return FALSE; }//IsBig_Endian()如何判断操作系统是32位还是16位 VC编程的话直接判断有没有定义_WIN32宏就可以了 bool bWin32; #ifdef _WIN32 bWin32=true; #else bWin32=false; #endif1.操作系统是16位还是32位是跟它的地址寻址方式相关的(需要CPU支持,但与CPU字长没有必然联系),因此可以直接通过指针(地址)的长度来判断: cout << (sizeof(int *)==4 ? "32 bit" : "16 bit") << endl; 2.如果不允许用sizeof,则通过整数的表示范围来判断,16位系统中整数最大为65535: unsigned int a = ~0; cout << (a>65535 ? "32 bit" : "16 bit") << endl;ArrayList和Vector的区别 Vector和ArrayList Vector和ArrayList在使用上非常相似,都可用来表示一组数量可变的对象应用的集合,并且可以随机地访问其中的元素。 Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好。 当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量翻倍,而ArrayList只增加50%的大小,这样,ArrayList就有利于节约内存空间ArrayList和Vector功能类似。 整体上ArrayList是Vector的“裸奔新版” Vector从Java 1.0起就存在,ArrayList从Java 1.2起才存在,较新。 所以Vector在JavaME、Card等各种微小版本都可以使用,而ArrayList不能 ArrayList不具备线程同步的安全性,但速度较快,所以叫裸奔。 Vector具备线程安全。 HashMap和Hashtable的区别 from: http://www.cnblogs.com/taotaoblog/archive/2009/09/19/1569958.html 1 HashMap不是线程安全的hastmap是一个接口 是map接口的子接口,是将键映射到值的对象,其中键和值都是对象,并且不能包含重复键,但可以包含重复值。HashMap允许null key和null value,而hashtable不允许。
2 HashTable是线程安全的一个Collection。 HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。volatile 和 synchronized关键字的区别一个变量声明为volatile,就意味着这个变量是随时会被其他线程修改的,因此不能将它cache在线程memory中.volatile是变量修饰符,而synchronized则作用于一段代码或方法 volatile关键字用于声明简单类型变量,如int、float、 boolean等数据类型。如果这些简单数据类型声明为volatile,对它们的操作就会变成原子级别的. 声明为volatile的简单变量如果当前值由该变量以前的值相关,那么volatile关键字不起作用,也就是说如下的表达式都不是原子操作: n = n + 1 ; n ++ ; 如果要想使这种情况变成原子操作,需要使用synchronized关键字.既然volatile关键字已经实现了线程间数据同步,又要 synchronized干什么呢?呵呵,它们之间有两点不同。首先,synchronized获得并释放监视器——如果两个线程使用了同一个对象锁,监视器能强制保证代码块同时只被一个线程所执行——这是众所周知的事实。但是,synchronized也同步内存:事实上,synchronized在“ 主”内存区域同步整个线程的内存。因此,执行geti3()方法做了如下几步: 1. 线程请求获得监视this对象的对象锁(假设未被锁,否则线程等待直到锁释放) 2. 线程内存的数据被消除,从“主”内存区域中读入(Java虚拟机能优化此步。。。[后面的不知道怎么表达,汗])3. 代码块被执行 4. 对于变量的任何改变现在可以安全地写到“主”内存区域中(不过geti3()方法不会改变变量值) 5. 线程释放监视this对象的对象锁 因此volatile只是在线程内存和“主”内存间同步某个变量的值,而synchronized通过锁定和解锁某个监视器同步所有变量的值。显然synchronized要比volatile消耗更多资源。 原子操作 "原子操作(atomic operation)是不需要synchronized"。所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行倒结束,中间不会有任何 context switch (切换到另一个线程)。 常见情况 如果问题中的变量除了long or double 以后的基本类型,对这些类型进行简单的赋值或者返回操作时是原子操作。为类型long and double 加上volatile修饰符,对这两个基本类型的操作也是原子的。 JVM中自增或减并不是原子操作,i++ or i-- 因为其中涉及一次读和写,在执行过程中可能被修改。TCP/IP建立连接的步骤在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认; 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态; 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。 完成三次握手,客户端与服务器开始传送数据,在上述过程中,还有一些重要的概念: 未连接队列:在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(syn=j)开设一个条目,该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于Syn_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入ESTABLISHED状态。 Backlog参数:表示未连接队列的最大容纳数目。 SYN-ACK 重传次数 服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同。 半连接存活时间:是指半连接队列的条目存活的最长时间,也即服务从收到SYN包到确认这个报文无效的最长时间,该时间值是所有重传请求包的最长等待时间总和。有时我们也称半连接存活时间为Timeout时间、SYN_RECV存活时间。